akashyadav758 Claude Opus 4.8 (1M context) commited on
Commit
5c7f4b5
·
1 Parent(s): 90bcc1f

Harden monitor (gate all routes), swap ChatGPT backend to free-Chatgpt-api, clean repo

Browse files

- Security: gate /, /api/*, /chrome.log behind API_KEY (Bearer / ?key= / apikey
cookie). Previously these were public — anyone could view+drive the logged-in
ChatGPT/Gemini/Google sessions. This was the likely "abusive" flag cause.
- ChatGPT backend: replace chatgpt-free-api with the free-Chatgpt-api rewrite
(drop-in: same 127.0.0.1:9225, same /api/chat + /v1/chat/completions). Update
Dockerfile COPY paths.
- Cleanup: drop leftover per-service Dockerfiles, redundant sub-READMEs, dev-only
docs/test scripts, the prebuilt linux binary, and cdp_* debug scripts.
- Docs: fix references, mark all routes key-gated, note the Space is now private.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files changed (42) hide show
  1. Dockerfile +3 -3
  2. HOWTOUSE.md +8 -8
  3. README.md +22 -21
  4. SETUP.md +2 -2
  5. chatgpt-free-api/Dockerfile +0 -17
  6. chatgpt-free-api/README.md +0 -56
  7. chatgpt-free-api/test.sh +0 -124
  8. docs/architecture.md +1 -1
  9. docs/deployment.md +2 -2
  10. docs/troubleshooting.md +2 -2
  11. flow-agent/Dockerfile +0 -16
  12. flow-agent/README.md +0 -468
  13. flow-agent/SNIFFING.md +0 -205
  14. flow-agent/error.md +0 -74
  15. flow-agent/test_api.py +0 -319
  16. {chatgpt-free-api → free-Chatgpt-api}/.gitignore +3 -0
  17. {chatgpt-free-api → free-Chatgpt-api}/agent.go +0 -0
  18. {chatgpt-free-api → free-Chatgpt-api}/api_bridge.go +0 -0
  19. {chatgpt-free-api → free-Chatgpt-api}/chatgpt.go +0 -0
  20. {chatgpt-free-api → free-Chatgpt-api}/config.go +0 -0
  21. {chatgpt-free-api → free-Chatgpt-api}/config.json +0 -0
  22. {chatgpt-free-api → free-Chatgpt-api}/cookies.go +0 -0
  23. {chatgpt-free-api → free-Chatgpt-api}/cookies_test.go +0 -0
  24. {chatgpt-free-api → free-Chatgpt-api}/extension.go +0 -0
  25. {chatgpt-free-api → free-Chatgpt-api}/go.mod +0 -0
  26. {chatgpt-free-api → free-Chatgpt-api}/go.sum +0 -0
  27. {chatgpt-free-api → free-Chatgpt-api}/gpt-extension/background.js +0 -0
  28. {chatgpt-free-api → free-Chatgpt-api}/gpt-extension/icon128.png +0 -0
  29. {chatgpt-free-api → free-Chatgpt-api}/gpt-extension/icon16.png +0 -0
  30. {chatgpt-free-api → free-Chatgpt-api}/gpt-extension/icon48.png +0 -0
  31. {chatgpt-free-api → free-Chatgpt-api}/gpt-extension/icon_large.png +0 -0
  32. {chatgpt-free-api → free-Chatgpt-api}/gpt-extension/manifest.json +0 -0
  33. {chatgpt-free-api → free-Chatgpt-api}/gpt-extension/popup.html +0 -0
  34. {chatgpt-free-api → free-Chatgpt-api}/gpt-extension/popup.js +0 -0
  35. {chatgpt-free-api → free-Chatgpt-api}/handlers.go +0 -0
  36. {chatgpt-free-api → free-Chatgpt-api}/helpers.go +0 -0
  37. {chatgpt-free-api → free-Chatgpt-api}/main.go +0 -0
  38. {chatgpt-free-api → free-Chatgpt-api}/sniff.go +0 -0
  39. free-gemini-api/.dockerignore +0 -8
  40. free-gemini-api/Dockerfile +0 -21
  41. free-gemini-api/README.md +0 -401
  42. monitor/main.go +36 -11
Dockerfile CHANGED
@@ -13,7 +13,7 @@ RUN go mod tidy && CGO_ENABLED=0 go build -ldflags="-s -w" -o /profilesync .
13
  # Build the ChatGPT API server (talks to gpt-extension on 127.0.0.1:9225).
14
  FROM golang:1.26-bookworm AS chatgpt-build
15
  WORKDIR /src
16
- COPY chatgpt-free-api/ ./
17
  RUN go mod download && CGO_ENABLED=0 go build -ldflags="-s -w" -o /agent .
18
 
19
  # Build the Gemini API server (talks to gemini-extension on 127.0.0.1:9226).
@@ -27,7 +27,7 @@ FROM akashyadav758/chrome:latest
27
  USER root
28
 
29
  # Copy extensions into the container
30
- COPY chatgpt-free-api/gpt-extension /opt/gpt-extension
31
  COPY free-gemini-api/gemini-extension /opt/gemini-extension
32
  COPY flow-agent/Flow-extension /opt/flow-extension
33
 
@@ -39,7 +39,7 @@ COPY --from=profilesync-build /profilesync /opt/profilesync/profilesync
39
 
40
  # Backend API servers (run on localhost; the monitor gateway fronts them).
41
  COPY --from=chatgpt-build /agent /opt/chatgpt/agent
42
- COPY chatgpt-free-api/config.json /opt/chatgpt/config.json
43
  COPY --from=gemini-build /free-gemini-api /opt/gemini-srv/free-gemini-api
44
  COPY flow-agent/ /opt/flow-srv/
45
 
 
13
  # Build the ChatGPT API server (talks to gpt-extension on 127.0.0.1:9225).
14
  FROM golang:1.26-bookworm AS chatgpt-build
15
  WORKDIR /src
16
+ COPY free-Chatgpt-api/ ./
17
  RUN go mod download && CGO_ENABLED=0 go build -ldflags="-s -w" -o /agent .
18
 
19
  # Build the Gemini API server (talks to gemini-extension on 127.0.0.1:9226).
 
27
  USER root
28
 
29
  # Copy extensions into the container
30
+ COPY free-Chatgpt-api/gpt-extension /opt/gpt-extension
31
  COPY free-gemini-api/gemini-extension /opt/gemini-extension
32
  COPY flow-agent/Flow-extension /opt/flow-extension
33
 
 
39
 
40
  # Backend API servers (run on localhost; the monitor gateway fronts them).
41
  COPY --from=chatgpt-build /agent /opt/chatgpt/agent
42
+ COPY free-Chatgpt-api/config.json /opt/chatgpt/config.json
43
  COPY --from=gemini-build /free-gemini-api /opt/gemini-srv/free-gemini-api
44
  COPY flow-agent/ /opt/flow-srv/
45
 
HOWTOUSE.md CHANGED
@@ -3,14 +3,14 @@
3
  One base URL fronts all three services. Every `/gpt`, `/gemini`, `/flow` call needs the
4
  `API_KEY` as a Bearer token. The monitor UI (`/`) needs no key.
5
 
6
- - **Base URL:** `https://akash1313-selfapi.hf.space`
7
  - **Auth header:** `Authorization: Bearer YOUR_API_KEY` *(your real key is in the gitignored `./api-key`)*
8
 
9
  > ⚠️ **You must be logged in** to ChatGPT / Gemini / Flow inside the browser
10
- > (`https://akash1313-selfapi.hf.space/`) for real responses. The servers reply even when
11
  > logged out, but with `extensionConnected:false` / empty data. Check first:
12
  > ```bash
13
- > curl -H "Authorization: Bearer YOUR_API_KEY" https://akash1313-selfapi.hf.space/gpt/health
14
  > ```
15
  > `extensionConnected:true` = ready.
16
 
@@ -27,12 +27,12 @@ One base URL fronts all three services. Every `/gpt`, `/gemini`, `/flow` call ne
27
 
28
  ```bash
29
  # Simple chat
30
- curl -X POST https://akash1313-selfapi.hf.space/gpt/api/chat \
31
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
32
  -d '{"prompt":"Write a haiku about the sea","wait_for_response":true}'
33
 
34
  # OpenAI-compatible (drop-in for OpenAI SDKs — set base_url=.../gpt/v1)
35
- curl -X POST https://akash1313-selfapi.hf.space/gpt/v1/chat/completions \
36
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
37
  -d '{"model":"gpt-5","messages":[{"role":"user","content":"hello"}],"stream":false}'
38
  ```
@@ -51,7 +51,7 @@ Optional fields: `"model"`, `"thinking_effort"`, `"conversation_id"` (continue a
51
  | `/gemini/output/<file>` | GET | — (generated media) |
52
 
53
  ```bash
54
- curl -X POST https://akash1313-selfapi.hf.space/gemini/chat \
55
  -H "Authorization: Bearer YOUR_API_KEY" \
56
  -d "prompt=Explain quantum entanglement simply&new_chat=true"
57
  ```
@@ -70,12 +70,12 @@ curl -X POST https://akash1313-selfapi.hf.space/gemini/chat \
70
 
71
  ```bash
72
  # Text-to-video (aspect: portrait|landscape ; duration: 4,6,8,10)
73
- curl -X POST https://akash1313-selfapi.hf.space/flow/generate/video \
74
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
75
  -d '{"prompt":"a cat surfing a wave, cinematic","aspect":"landscape","duration":8}'
76
 
77
  # Text-to-image
78
- curl -X POST https://akash1313-selfapi.hf.space/flow/generate/image \
79
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
80
  -d '{"prompt":"neon city at night","aspect":"square"}'
81
  ```
 
3
  One base URL fronts all three services. Every `/gpt`, `/gemini`, `/flow` call needs the
4
  `API_KEY` as a Bearer token. The monitor UI (`/`) needs no key.
5
 
6
+ - **Base URL:** `https://akash1313-selfapi-v2.hf.space`
7
  - **Auth header:** `Authorization: Bearer YOUR_API_KEY` *(your real key is in the gitignored `./api-key`)*
8
 
9
  > ⚠️ **You must be logged in** to ChatGPT / Gemini / Flow inside the browser
10
+ > (`https://akash1313-selfapi-v2.hf.space/`) for real responses. The servers reply even when
11
  > logged out, but with `extensionConnected:false` / empty data. Check first:
12
  > ```bash
13
+ > curl -H "Authorization: Bearer YOUR_API_KEY" https://akash1313-selfapi-v2.hf.space/gpt/health
14
  > ```
15
  > `extensionConnected:true` = ready.
16
 
 
27
 
28
  ```bash
29
  # Simple chat
30
+ curl -X POST https://akash1313-selfapi-v2.hf.space/gpt/api/chat \
31
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
32
  -d '{"prompt":"Write a haiku about the sea","wait_for_response":true}'
33
 
34
  # OpenAI-compatible (drop-in for OpenAI SDKs — set base_url=.../gpt/v1)
35
+ curl -X POST https://akash1313-selfapi-v2.hf.space/gpt/v1/chat/completions \
36
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
37
  -d '{"model":"gpt-5","messages":[{"role":"user","content":"hello"}],"stream":false}'
38
  ```
 
51
  | `/gemini/output/<file>` | GET | — (generated media) |
52
 
53
  ```bash
54
+ curl -X POST https://akash1313-selfapi-v2.hf.space/gemini/chat \
55
  -H "Authorization: Bearer YOUR_API_KEY" \
56
  -d "prompt=Explain quantum entanglement simply&new_chat=true"
57
  ```
 
70
 
71
  ```bash
72
  # Text-to-video (aspect: portrait|landscape ; duration: 4,6,8,10)
73
+ curl -X POST https://akash1313-selfapi-v2.hf.space/flow/generate/video \
74
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
75
  -d '{"prompt":"a cat surfing a wave, cinematic","aspect":"landscape","duration":8}'
76
 
77
  # Text-to-image
78
+ curl -X POST https://akash1313-selfapi-v2.hf.space/flow/generate/image \
79
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
80
  -d '{"prompt":"neon city at night","aspect":"square"}'
81
  ```
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Selfapi
3
  emoji: 📊
4
  colorFrom: gray
5
  colorTo: blue
@@ -8,9 +8,9 @@ app_port: 3001
8
  pinned: false
9
  ---
10
 
11
- # Selfapi — Headless Chrome + Unpacked Extensions
12
 
13
- A [Hugging Face Space](https://huggingface.co/spaces/akash1313/selfapi) that runs a
14
  persistent, headless **Chrome for Testing** browser inside Docker with three custom
15
  unpacked extensions auto-loaded, plus a live web monitor to watch the browser in real time.
16
 
@@ -25,12 +25,12 @@ automate workflows for ChatGPT, Google Gemini, and Google Flow.
25
 
26
  | Extension | Source dir | Loaded at | What it does |
27
  |-----------|-----------|-----------|--------------|
28
- | **Gpt Agent Api** | `chatgpt-free-api/gpt-extension` | `/opt/gpt-extension` | Auto-syncs ChatGPT cookies to a local ChatGPT Free API server |
29
  | **Gemini Api Agent** | `free-gemini-api/gemini-extension` | `/opt/gemini-extension` | Auto-syncs Google Gemini cookies to a local Free Gemini API server |
30
  | **Flow Agent** | `flow-agent/Flow-extension` | `/opt/flow-extension` | Automates Google Flow — T2V / V2V / I2V video + T2I / I2I image generation |
31
 
32
  All three are Manifest V3 extensions with background service workers. Each subfolder
33
- also contains the matching backend server and its own README.
34
 
35
  ---
36
 
@@ -42,9 +42,9 @@ run yourself — see each subproject's README for setup):
42
 
43
  | Project | Server | Talks to | Purpose |
44
  |---------|--------|----------|---------|
45
- | [`chatgpt-free-api`](chatgpt-free-api/README.md) | Go | `127.0.0.1:9225` | ChatGPT backend API from your logged-in session |
46
- | [`free-gemini-api`](free-gemini-api/README.md) | Go reverse-proxy | local server | Gemini text / Imagen 3 images / Gemini video |
47
- | [`flow-agent`](flow-agent/README.md) | Python FastAPI + CLI | `127.0.0.1:8100` | Google Flow T2V / V2V / I2V video + T2I / I2I images |
48
 
49
  > ✅ The HF Space now runs **all three servers in the same container** as Chrome, and the
50
  > monitor doubles as a **single API gateway** that fronts them on one public port — see
@@ -162,7 +162,7 @@ Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/14
162
 
163
  A **macOS UA on a Linux box is an inconsistency** that Cloudflare Turnstile flags, causing
164
  the ChatGPT "verify you are human" check to loop forever (the tick never clears). The browser
165
- UA lives in `start_hf.sh`; the ChatGPT backend (`chatgpt-free-api/cookies.go`) uses the **same
166
  UA and Chrome version (145)** so the `cf_clearance` cookie — which Cloudflare binds to the
167
  exact UA — stays valid across the browser and the backend.
168
 
@@ -172,11 +172,11 @@ exact UA — stays valid across the browser and the backend.
172
 
173
  | URL | Description |
174
  |-----|-------------|
175
- | `https://akash1313-selfapi.hf.space/` | Live Chrome monitor UI (open, no key) |
176
- | `https://akash1313-selfapi.hf.space/chrome.log` | Streaming Chrome log (debugging) |
177
- | `https://akash1313-selfapi.hf.space/gpt/…` | ChatGPT API (gateway → `127.0.0.1:9225`) |
178
- | `https://akash1313-selfapi.hf.space/gemini/…` | Gemini API (gateway → `127.0.0.1:8000`) |
179
- | `https://akash1313-selfapi.hf.space/flow/…` | Flow API (gateway → `127.0.0.1:8101`) |
180
  | `127.0.0.1:9222` (in-container) | Chrome DevTools Protocol |
181
  | `:9223` | CDP proxied for external tools (via socat) |
182
 
@@ -190,21 +190,22 @@ gateway strips the prefix and forwards to the server on localhost:
190
 
191
  | Prefix | Backend | Example endpoints |
192
  |--------|---------|-------------------|
193
- | `/gpt/` | chatgpt-free-api `:9225` | `/gpt/api/chat`, `/gpt/v1/chat/completions`, `/gpt/health` |
194
  | `/gemini/` | free-gemini-api `:8000` | `/gemini/chat`, `/gemini/status`, `/gemini/output/*` |
195
  | `/flow/` | flow-agent `:8101` | `/flow/generate/video`, `/flow/generate/image`, `/flow/health` |
196
 
197
  ### Auth — required
198
 
199
- The three prefixes are gated by an **`API_KEY`** Space secret. Every request must send it as a
200
- Bearer token (or `?key=`). **Fail-closed:** if `API_KEY` is unset the gateway returns `503`, so
201
- the logged-in accounts are never accidentally exposed. The monitor UI (`/`, `/chrome.log`) stays
202
- open.
 
203
 
204
  1. Set the Space secret **`API_KEY`** (Settings → Variables and secrets) to a strong random string.
205
  2. Call it:
206
  ```bash
207
- curl -X POST https://akash1313-selfapi.hf.space/gpt/api/chat \
208
  -H "Authorization: Bearer $API_KEY" \
209
  -H "Content-Type: application/json" \
210
  -d '{"message":"hello"}'
@@ -222,7 +223,7 @@ chrome-space/
222
  ├── start_hf.sh # container entrypoint / Chrome boot sequence
223
  ├── profilesync/ # Go tool: Chrome profile <-> Postgres snapshot
224
  ├── monitor/ # Go 3-tab live monitor (GPT / Gemini / Flow)
225
- ├── chatgpt-free-api/ # ChatGPT Free API server + gpt-extension
226
  ├── free-gemini-api/ # Free Gemini API server + gemini-extension
227
  └── flow-agent/ # Flow automation CLI + Flow-extension
228
  ```
 
1
  ---
2
+ title: Selfapi-v2
3
  emoji: 📊
4
  colorFrom: gray
5
  colorTo: blue
 
8
  pinned: false
9
  ---
10
 
11
+ # Selfapi-v2 — Headless Chrome + Unpacked Extensions
12
 
13
+ A [Hugging Face Space](https://huggingface.co/spaces/akash1313/selfapi-v2) that runs a
14
  persistent, headless **Chrome for Testing** browser inside Docker with three custom
15
  unpacked extensions auto-loaded, plus a live web monitor to watch the browser in real time.
16
 
 
25
 
26
  | Extension | Source dir | Loaded at | What it does |
27
  |-----------|-----------|-----------|--------------|
28
+ | **Gpt Agent Api** | `free-Chatgpt-api/gpt-extension` | `/opt/gpt-extension` | Auto-syncs ChatGPT cookies to a local ChatGPT Free API server |
29
  | **Gemini Api Agent** | `free-gemini-api/gemini-extension` | `/opt/gemini-extension` | Auto-syncs Google Gemini cookies to a local Free Gemini API server |
30
  | **Flow Agent** | `flow-agent/Flow-extension` | `/opt/flow-extension` | Automates Google Flow — T2V / V2V / I2V video + T2I / I2I image generation |
31
 
32
  All three are Manifest V3 extensions with background service workers. Each subfolder
33
+ also contains the matching backend server.
34
 
35
  ---
36
 
 
42
 
43
  | Project | Server | Talks to | Purpose |
44
  |---------|--------|----------|---------|
45
+ | `free-Chatgpt-api` | Go | `127.0.0.1:9225` | ChatGPT backend API from your logged-in session |
46
+ | `free-gemini-api` | Go reverse-proxy | local server | Gemini text / Imagen 3 images / Gemini video |
47
+ | `flow-agent` | Python FastAPI + CLI | `127.0.0.1:8100` | Google Flow T2V / V2V / I2V video + T2I / I2I images |
48
 
49
  > ✅ The HF Space now runs **all three servers in the same container** as Chrome, and the
50
  > monitor doubles as a **single API gateway** that fronts them on one public port — see
 
162
 
163
  A **macOS UA on a Linux box is an inconsistency** that Cloudflare Turnstile flags, causing
164
  the ChatGPT "verify you are human" check to loop forever (the tick never clears). The browser
165
+ UA lives in `start_hf.sh`; the ChatGPT backend (`free-Chatgpt-api/cookies.go`) uses the **same
166
  UA and Chrome version (145)** so the `cf_clearance` cookie — which Cloudflare binds to the
167
  exact UA — stays valid across the browser and the backend.
168
 
 
172
 
173
  | URL | Description |
174
  |-----|-------------|
175
+ | `https://akash1313-selfapi-v2.hf.space/` | Live Chrome monitor UI — **key required** (open `/?key=YOUR_API_KEY` once; it sets a cookie) |
176
+ | `https://akash1313-selfapi-v2.hf.space/chrome.log` | Streaming Chrome log — **key required** |
177
+ | `https://akash1313-selfapi-v2.hf.space/gpt/…` | ChatGPT API (gateway → `127.0.0.1:9225`) |
178
+ | `https://akash1313-selfapi-v2.hf.space/gemini/…` | Gemini API (gateway → `127.0.0.1:8000`) |
179
+ | `https://akash1313-selfapi-v2.hf.space/flow/…` | Flow API (gateway → `127.0.0.1:8101`) |
180
  | `127.0.0.1:9222` (in-container) | Chrome DevTools Protocol |
181
  | `:9223` | CDP proxied for external tools (via socat) |
182
 
 
190
 
191
  | Prefix | Backend | Example endpoints |
192
  |--------|---------|-------------------|
193
+ | `/gpt/` | free-Chatgpt-api `:9225` | `/gpt/api/chat`, `/gpt/v1/chat/completions`, `/gpt/health` |
194
  | `/gemini/` | free-gemini-api `:8000` | `/gemini/chat`, `/gemini/status`, `/gemini/output/*` |
195
  | `/flow/` | flow-agent `:8101` | `/flow/generate/video`, `/flow/generate/image`, `/flow/health` |
196
 
197
  ### Auth — required
198
 
199
+ **Every** route — the API prefixes, the monitor UI (`/`), `/api/*`, `/chrome.log`, `/logs/*` — is
200
+ gated by an **`API_KEY`** Space secret. Send it as a Bearer token, `?key=`, or (for the browser UI)
201
+ open `/?key=YOUR_API_KEY` once to set an `apikey` cookie. **Fail-closed:** if `API_KEY` is unset
202
+ every route returns `503`, so the logged-in accounts are never exposed. This Space is also
203
+ **private** on Hugging Face, so the URL itself requires HF auth — defense in depth.
204
 
205
  1. Set the Space secret **`API_KEY`** (Settings → Variables and secrets) to a strong random string.
206
  2. Call it:
207
  ```bash
208
+ curl -X POST https://akash1313-selfapi-v2.hf.space/gpt/api/chat \
209
  -H "Authorization: Bearer $API_KEY" \
210
  -H "Content-Type: application/json" \
211
  -d '{"message":"hello"}'
 
223
  ├── start_hf.sh # container entrypoint / Chrome boot sequence
224
  ├── profilesync/ # Go tool: Chrome profile <-> Postgres snapshot
225
  ├── monitor/ # Go 3-tab live monitor (GPT / Gemini / Flow)
226
+ ├── free-Chatgpt-api/ # ChatGPT Free API server + gpt-extension
227
  ├── free-gemini-api/ # Free Gemini API server + gemini-extension
228
  └── flow-agent/ # Flow automation CLI + Flow-extension
229
  ```
SETUP.md CHANGED
@@ -9,8 +9,8 @@ Very short guide. Runs the browser + all 3 API servers on your own machine/serve
9
 
10
  ## 2. Get the code
11
  ```bash
12
- git clone https://huggingface.co/spaces/akash1313/selfapi
13
- cd selfapi
14
  ```
15
 
16
  ## 3. Run it
 
9
 
10
  ## 2. Get the code
11
  ```bash
12
+ git clone https://huggingface.co/spaces/akash1313/selfapi-v2
13
+ cd selfapi-v2
14
  ```
15
 
16
  ## 3. Run it
chatgpt-free-api/Dockerfile DELETED
@@ -1,17 +0,0 @@
1
- # ChatGPT Free API agent — talks to the gpt-extension over ws/http on 127.0.0.1:9225.
2
- FROM golang:1.26-bookworm AS builder
3
- WORKDIR /app
4
- COPY go.mod go.sum ./
5
- RUN go mod download
6
- COPY . .
7
- RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o agent .
8
-
9
- FROM debian:12-slim
10
- RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && \
11
- rm -rf /var/lib/apt/lists/*
12
- WORKDIR /app
13
- COPY --from=builder /app/agent .
14
- COPY config.json .
15
-
16
- EXPOSE 9225
17
- CMD ["./agent"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
chatgpt-free-api/README.md DELETED
@@ -1,56 +0,0 @@
1
- # ChatGPT Free API Agent
2
-
3
- A flat-structure Go server that connects with the Chrome extension (`gpt-extension`) to execute ChatGPT backend API requests directly from your authenticated browser session.
4
-
5
- ## Setup & Running
6
-
7
- 1. **Build & Run the Server:**
8
- ```bash
9
- go build -o agent .
10
- ./agent
11
- ```
12
- 2. **Load Chrome Extension:**
13
- - Open `chrome://extensions` in Chrome.
14
- - Enable **Developer mode** (top-right).
15
- - Click **Load unpacked** and select the `gpt-extension` folder (in the parent directory).
16
- 3. **Login to ChatGPT:**
17
- - Open `https://chatgpt.com/` and log in. The extension will automatically connect to the running Go agent (green status badge = connected).
18
-
19
- ---
20
-
21
- ## API Usage
22
-
23
- ### 1. Send Chat Request
24
- ```bash
25
- curl -X POST "http://127.0.0.1:9225/api/chat" \
26
- -H "Content-Type: application/json" \
27
- -d '{"prompt": "Why is sky blue?", "conversation_id": ""}'
28
- ```
29
-
30
- ### 2. Bulk Sequential Requests
31
- ```bash
32
- curl -X POST "http://127.0.0.1:9225/api/chat/bulk" \
33
- -H "Content-Type: application/json" \
34
- -d '{"prompts": ["hello", "how are you"]}'
35
- ```
36
-
37
- ### 3. Edit Existing Message
38
- ```bash
39
- curl -X POST "http://127.0.0.1:9225/api/chat/edit" \
40
- -H "Content-Type: application/json" \
41
- -d '{"prompt": "updated prompt", "conversation_id": "conv-id", "message_id": "msg-id", "parent_id": "parent-id"}'
42
- ```
43
-
44
- ### 4. Health & Cookie Status
45
- - **Health Check:** `GET http://127.0.0.1:9225/health`
46
- - **Cookie Status:** `GET http://127.0.0.1:9225/api/cookies/status`
47
-
48
- ---
49
-
50
- ## Testing
51
-
52
- Run the integration tests (requires agent running on port 9225):
53
- ```bash
54
- ./test.sh # Run all tests (text, thread, bulk, image gen/edit)
55
- ./test_image_only.sh # Run only image generation/editing tests
56
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
chatgpt-free-api/test.sh DELETED
@@ -1,124 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Unset proxy variables for local communication
4
- unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY no_proxy
5
-
6
- # Colors for output
7
- GREEN='\033[0;32m'
8
- RED='\033[0;31m'
9
- YELLOW='\033[0;33m'
10
- BLUE='\033[0;34m'
11
- NC='\033[0m' # No Color
12
-
13
- echo -e "${BLUE}==================================================${NC}"
14
- echo -e "${BLUE} ChatGPT Free API Integration Test ${NC}"
15
- echo -e "${BLUE}==================================================${NC}"
16
-
17
- # Check if agent is running on port 9225
18
- echo "🔍 Checking if agent is running on port 9225..."
19
- if ! curl -s --connect-timeout 2 http://127.0.0.1:9225/health >/dev/null; then
20
- echo -e "${RED}❌ Error: Agent is not running on port 9225!${NC}"
21
- echo -e "💡 Please start the server separately first by running: ${YELLOW}./agent${NC} or ${YELLOW}go run main.go${NC}"
22
- exit 1
23
- fi
24
- echo -e "${GREEN}✅ Agent detected on port 9225! Running tests...${NC}"
25
-
26
- # Test 1: Check cookie status
27
- echo -e "\n${BLUE}[Test 1] Checking cookie status...${NC}"
28
- STATUS_RESP=$(curl -s http://127.0.0.1:9225/api/cookies/status)
29
- echo "Response: $STATUS_RESP"
30
- if [[ "$STATUS_RESP" == *"has_cookies\":true"* ]]; then
31
- TEST1_STATUS="${GREEN}PASSED${NC}"
32
- else
33
- TEST1_STATUS="${RED}FAILED (No cookies sync)${NC}"
34
- fi
35
-
36
- # Test 2: Send basic chat test
37
- echo -e "\n${BLUE}[Test 2] Sending basic text chat prompt...${NC}"
38
- CHAT_RESP=$(curl -s -X POST http://127.0.0.1:9225/api/chat \
39
- -H "Content-Type: application/json" \
40
- -d '{"prompt": "Tell me a short programmer joke."}')
41
- echo "Response: $CHAT_RESP"
42
-
43
- CONV_ID=$(echo "$CHAT_RESP" | grep -o '"conversation_id":"[^"]*' | cut -d'"' -f4)
44
- if [ -n "$CONV_ID" ]; then
45
- TEST2_STATUS="${GREEN}PASSED${NC}"
46
- else
47
- TEST2_STATUS="${RED}FAILED (No response or conversation ID)${NC}"
48
- fi
49
-
50
- # Test 3: Conversation thread continuity
51
- if [ -n "$CONV_ID" ]; then
52
- echo -e "\n${BLUE}[Test 3] Testing thread continuity...${NC}"
53
- THREAD_RESP=$(curl -s -X POST http://127.0.0.1:9225/api/chat \
54
- -H "Content-Type: application/json" \
55
- -d "{\"prompt\": \"Explain that joke.\", \"conversation_id\": \"$CONV_ID\"}")
56
- echo "Response: $THREAD_RESP"
57
- if [[ "$THREAD_RESP" == *"ok\":true"* ]]; then
58
- TEST3_STATUS="${GREEN}PASSED${NC}"
59
- else
60
- TEST3_STATUS="${RED}FAILED (Thread reply failed)${NC}"
61
- fi
62
- else
63
- TEST3_STATUS="${YELLOW}SKIPPED (No conversation ID)${NC}"
64
- fi
65
-
66
- # Test 4: Bulk chat request
67
- echo -e "\n${BLUE}[Test 4] Testing bulk chat request...${NC}"
68
- BULK_RESP=$(curl -s -X POST http://127.0.0.1:9225/api/chat/bulk \
69
- -H "Content-Type: application/json" \
70
- -d '{"prompts": ["What is 2+2?", "What is Go?"], "wait_for_response": true}')
71
- echo "Response: $BULK_RESP"
72
- if [[ "$BULK_RESP" == *"ok\":true"* ]]; then
73
- TEST4_STATUS="${GREEN}PASSED${NC}"
74
- else
75
- TEST4_STATUS="${RED}FAILED${NC}"
76
- fi
77
-
78
- # Test 5: Image generation (GPT-2)
79
- echo -e "\n${BLUE}[Test 5] Testing GPT-2 image generation (Cute baby dragon)...${NC}"
80
- echo "⏳ Polling for GPT-2 generation, this will take 15-35 seconds..."
81
- GEN_RESP=$(curl -s -X POST http://127.0.0.1:9225/api/chat \
82
- -H "Content-Type: application/json" \
83
- -d '{"prompt": "Create a cute 3D cartoon baby dragon sitting on a small chest of gold. Directly generate the image now without asking any questions or confirmation."}')
84
- echo "Response: $GEN_RESP"
85
-
86
- # Extract generated image path
87
- GEN_IMAGE_PATH=$(echo "$GEN_RESP" | grep -o '"images":\["[^"]*' | cut -d'"' -f4)
88
- if [ -n "$GEN_IMAGE_PATH" ] && [ -f "$GEN_IMAGE_PATH" ]; then
89
- TEST5_STATUS="${GREEN}PASSED ($GEN_IMAGE_PATH)${NC}"
90
- else
91
- TEST5_STATUS="${RED}FAILED (Image file not generated/saved)${NC}"
92
- fi
93
-
94
- # Test 6: Image editing (GPT-2 Edit/Vision)
95
- if [ -n "$GEN_IMAGE_PATH" ] && [ -f "$GEN_IMAGE_PATH" ]; then
96
- echo -e "\n${BLUE}[Test 6] Testing GPT-2 image editing (Adding wizard hat)...${NC}"
97
- echo "⏳ Uploading source image and polling for edit, this will take 15-35 seconds..."
98
- EDIT_RESP=$(curl -s -X POST http://127.0.0.1:9225/api/chat/edit \
99
- -F "prompt=Add a small glowing wizard hat to the head of this dragon." \
100
- -F "image=@$GEN_IMAGE_PATH")
101
- echo "Response: $EDIT_RESP"
102
-
103
- EDIT_IMAGE_PATH=$(echo "$EDIT_RESP" | grep -o '"images":\["[^"]*' | cut -d'"' -f4)
104
- if [ -n "$EDIT_IMAGE_PATH" ] && [ -f "$EDIT_IMAGE_PATH" ]; then
105
- TEST6_STATUS="${GREEN}PASSED ($EDIT_IMAGE_PATH)${NC}"
106
- else
107
- TEST6_STATUS="${RED}FAILED (Edited image file not generated/saved)${NC}"
108
- fi
109
- else
110
- TEST6_STATUS="${YELLOW}SKIPPED (No source image generated in Test 5)${NC}"
111
- fi
112
-
113
- echo -e "\n${BLUE}==================================================${NC}"
114
- echo -e "${BLUE} Test Summary ${NC}"
115
- echo -e "${BLUE}==================================================${NC}"
116
- echo -e "1. Cookie Status: $TEST1_STATUS"
117
- echo -e "2. Basic Chat: $TEST2_STATUS"
118
- echo -e "3. Thread Continuity: $TEST3_STATUS"
119
- echo -e "4. Bulk Chat: $TEST4_STATUS"
120
- echo -e "5. GPT-2 Gen: $TEST5_STATUS"
121
- echo -e "6. GPT-2 Image Editing: $TEST6_STATUS"
122
- echo -e "${BLUE}==================================================${NC}"
123
-
124
- echo -e "\n${GREEN}✅ Tests completed!${NC}\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docs/architecture.md CHANGED
@@ -40,5 +40,5 @@ the 3 extensions. Each server logs to `/home/chrome/{chatgpt,gemini,flow}.log`.
40
  ## Components added on top of the base image
41
  - `monitor/` — Go UI, now also the **reverse-proxy gateway** (`gatewayHandler`, `authOK`).
42
  - `profilesync/` — Go tool, Chrome profile ⇄ Postgres snapshot.
43
- - `chatgpt-free-api/`, `free-gemini-api/` (Go) + `flow-agent/` (Python/FastAPI) — the 3 servers,
44
  built/installed into the image by the `Dockerfile`.
 
40
  ## Components added on top of the base image
41
  - `monitor/` — Go UI, now also the **reverse-proxy gateway** (`gatewayHandler`, `authOK`).
42
  - `profilesync/` — Go tool, Chrome profile ⇄ Postgres snapshot.
43
+ - `free-Chatgpt-api/`, `free-gemini-api/` (Go) + `flow-agent/` (Python/FastAPI) — the 3 servers,
44
  built/installed into the image by the `Dockerfile`.
docs/deployment.md CHANGED
@@ -16,13 +16,13 @@ The `origin` remote embeds a token: `https://<user>:<hf_token>@huggingface.co/sp
16
  - The token **must belong to the Space owner** (`akash1313`) with `repo.write`. A token from a
17
  different account → `pre-receive hook declined: You are not authorized to push`.
18
  - Rotate/replace the token in the URL with:
19
- `git remote set-url origin https://akash1313:<NEW_TOKEN>@huggingface.co/spaces/akash1313/selfapi`
20
  - Local token files (`hf-token`, `neon-db`, `api-key`) are gitignored — never commit them.
21
 
22
  ### Watch the build
23
  ```bash
24
  curl -s -H "Authorization: Bearer <hf_token>" \
25
- https://huggingface.co/api/spaces/akash1313/selfapi/runtime
26
  # stage: RUNNING_BUILDING → RUNNING_APP_STARTING → RUNNING (errors: BUILD_ERROR / RUNTIME_ERROR)
27
  ```
28
 
 
16
  - The token **must belong to the Space owner** (`akash1313`) with `repo.write`. A token from a
17
  different account → `pre-receive hook declined: You are not authorized to push`.
18
  - Rotate/replace the token in the URL with:
19
+ `git remote set-url origin https://akash1313:<NEW_TOKEN>@huggingface.co/spaces/akash1313/selfapi-v2`
20
  - Local token files (`hf-token`, `neon-db`, `api-key`) are gitignored — never commit them.
21
 
22
  ### Watch the build
23
  ```bash
24
  curl -s -H "Authorization: Bearer <hf_token>" \
25
+ https://huggingface.co/api/spaces/akash1313/selfapi-v2/runtime
26
  # stage: RUNNING_BUILDING → RUNNING_APP_STARTING → RUNNING (errors: BUILD_ERROR / RUNTIME_ERROR)
27
  ```
28
 
docs/troubleshooting.md CHANGED
@@ -7,7 +7,7 @@ Every issue we actually hit, and the fix.
7
  | Symptom | Cause → Fix |
8
  |---------|-------------|
9
  | `pre-receive hook declined: You are not authorized to push` | The token in the `origin` URL isn't the Space owner's. Use an `akash1313` token with `repo.write` (see [deployment.md](deployment.md)). |
10
- | `Repository not found` on push | Remote points to a Space that doesn't exist. `git remote -v` and fix the name (we deploy to `akash1313/selfapi`). |
11
  | Build `BUILD_ERROR` after bumping a server | `go.mod` Go version > build-stage image. Raise the `FROM golang:X` in the Dockerfile. |
12
  | Python `externally-managed-environment` during pip | Debian 12 PEP-668. We use `pip3 install --break-system-packages` (already in Dockerfile). |
13
  | Frequent restarts | Normal: **every `git push` and every secret change rebuilds.** Batch edits into one push. Not a CPU/RAM issue (cpu-basic = 2 vCPU / 16 GB; usage ~1–2 GB). |
@@ -26,7 +26,7 @@ Every issue we actually hit, and the fix.
26
  | Symptom | Cause → Fix |
27
  |---------|-------------|
28
  | Login lost after restart | `DATABASE_URL` unset or DB unreachable (HF). Set the Neon secret; verify a row in `chrome_profile`. |
29
- | ChatGPT Cloudflare "verify you are human" loops | UA/OS mismatch. The UA **must be Linux** (the Space runs Linux) — it's set in `start_hf.sh` and `chatgpt-free-api/cookies.go` (Chrome 145). If it still loops, it's the datacenter IP (HF=AWS) → use a residential `--proxy-server`. |
30
  | `extensionConnected:false` / `has_flow_key:false` on `/…/health` | The in-Chrome extension hasn't connected to its server yet. It connects when (a) Chrome has loaded the extension and (b) **you're logged in** to that service. Open the monitor UI, log in, wait. Extensions auto-retry (~5 s reconnect alarm). |
31
  | Extension never connects + API calls **hang forever** (`DidStartWorkerFail` in `chrome.log`) | Chrome was launched with renderer-capping flags (`--renderer-process-limit=1`, `--process-per-site`, `--no-zygote`). Each extension's MV3 service worker is its own renderer and the chat flow injects via `executeScript`; capping renderers starves them → workers fail to start and `executeScript` hangs. **Removed from `start_hf.sh`** — keep Chrome multi-process (HF has 16 GB). The UI chatting fine while the API hangs is the tell. |
32
  | Backend server logs | `GET /logs/{chatgpt,gemini,flow,monitor}` (API-key gated) tails each server's log without shelling into the container. |
 
7
  | Symptom | Cause → Fix |
8
  |---------|-------------|
9
  | `pre-receive hook declined: You are not authorized to push` | The token in the `origin` URL isn't the Space owner's. Use an `akash1313` token with `repo.write` (see [deployment.md](deployment.md)). |
10
+ | `Repository not found` on push | Remote points to a Space that doesn't exist. `git remote -v` and fix the name (we deploy to `akash1313/selfapi-v2`). |
11
  | Build `BUILD_ERROR` after bumping a server | `go.mod` Go version > build-stage image. Raise the `FROM golang:X` in the Dockerfile. |
12
  | Python `externally-managed-environment` during pip | Debian 12 PEP-668. We use `pip3 install --break-system-packages` (already in Dockerfile). |
13
  | Frequent restarts | Normal: **every `git push` and every secret change rebuilds.** Batch edits into one push. Not a CPU/RAM issue (cpu-basic = 2 vCPU / 16 GB; usage ~1–2 GB). |
 
26
  | Symptom | Cause → Fix |
27
  |---------|-------------|
28
  | Login lost after restart | `DATABASE_URL` unset or DB unreachable (HF). Set the Neon secret; verify a row in `chrome_profile`. |
29
+ | ChatGPT Cloudflare "verify you are human" loops | UA/OS mismatch. The UA **must be Linux** (the Space runs Linux) — it's set in `start_hf.sh` and `free-Chatgpt-api/cookies.go` (Chrome 145). If it still loops, it's the datacenter IP (HF=AWS) → use a residential `--proxy-server`. |
30
  | `extensionConnected:false` / `has_flow_key:false` on `/…/health` | The in-Chrome extension hasn't connected to its server yet. It connects when (a) Chrome has loaded the extension and (b) **you're logged in** to that service. Open the monitor UI, log in, wait. Extensions auto-retry (~5 s reconnect alarm). |
31
  | Extension never connects + API calls **hang forever** (`DidStartWorkerFail` in `chrome.log`) | Chrome was launched with renderer-capping flags (`--renderer-process-limit=1`, `--process-per-site`, `--no-zygote`). Each extension's MV3 service worker is its own renderer and the chat flow injects via `executeScript`; capping renderers starves them → workers fail to start and `executeScript` hangs. **Removed from `start_hf.sh`** — keep Chrome multi-process (HF has 16 GB). The UI chatting fine while the API hangs is the tell. |
32
  | Backend server logs | `GET /logs/{chatgpt,gemini,flow,monitor}` (API-key gated) tails each server's log without shelling into the container. |
flow-agent/Dockerfile DELETED
@@ -1,16 +0,0 @@
1
- # Flow Agent FastAPI server — talks to the Flow extension.
2
- # Public HTTP API : 127.0.0.1:8101 (uvicorn / FastAPI)
3
- # Extension callback HTTP : 127.0.0.1:8100 (HTTP_PORT, ExtensionBridge — hardcoded in extension)
4
- # cookie/token WebSocket : 127.0.0.1:9227 (WS_PORT)
5
- FROM python:3.11-slim
6
-
7
- WORKDIR /app
8
- COPY requirements.txt .
9
- RUN pip install --no-cache-dir -r requirements.txt
10
- COPY . .
11
-
12
- ENV WS_PORT=9227 \
13
- HTTP_PORT=8100
14
-
15
- EXPOSE 8100 8101 9227
16
- CMD ["uvicorn", "cli.api:app", "--host", "127.0.0.1", "--port", "8101"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
flow-agent/README.md DELETED
@@ -1,468 +0,0 @@
1
- <div align="center">
2
-
3
- # ⚡ Flow Agent
4
-
5
- ### Generate AI videos & images via HTTP/HTTPS API Server or CLI — no API key, no limits.
6
-
7
- **Omni Flash** for cinematic video generation · **Nano Banana 2** for unlimited image creation
8
- FastAPI Integration · Auto watermark removal · Reference-based editing · Zero setup.
9
-
10
- ---
11
-
12
- 🎬 `T2V` `V2V` `I2V` — Video generation with auto watermark clean *(uses credits)*
13
- 🖼️ `T2I` `I2I` — Unlimited image generation with reference support *(no credits needed)*
14
- 🔑 Uses your Google account via Chrome extension — **no API key required**
15
- 🌐 FastAPI HTTP/HTTPS Server — **perfect for n8n & external automation**
16
-
17
- </div>
18
-
19
-
20
- ## ✅ Features & Status
21
-
22
- | Feature | What it does | Time | Status |
23
- |---------|-------------|------|--------|
24
- | **T2V** | Generate video from text prompt | ~44s | ✅ Working |
25
- | **T2I** | Generate image from text prompt | ~10-30s | ✅ Working |
26
- | **V2V** | Edit/restyle existing video | ~3min | ✅ Working |
27
- | **I2I** | Edit image with reference | ~10-30s | ✅ Working |
28
- | **I2V** | Animate a still image into video | ~44s | ✅ Working |
29
- | **FL** | First + Last frame video control | ~44s | ✅ Working |
30
- | **R2V** | Reference-based video generation | ~44s | ✅ Working |
31
- | **Upload** | Upload video/image to Flow | ~12s | ✅ Working |
32
- | **Watermark Remove** | Auto-remove Gemini watermark (~1s) | ~1s | ✅ Auto |
33
- | **Auto-Retry** | Auto-open/refresh Flow tab for token | auto | ✅ Built-in |
34
- | **API Sniffer** | Discover new endpoints/payloads | - | ✅ Working |
35
-
36
- ---
37
-
38
- ## 📋 Prerequisites
39
-
40
- | Requirement | Details |
41
- |-------------|---------|
42
- | **Python** | 3.9 or higher |
43
- | **Chrome** | Latest version |
44
- | **Google Account** | Logged into Flow |
45
- | **ffmpeg** | Only for V2V merge (optional) |
46
-
47
- ---
48
-
49
- ## 🛠️ Installation (Step by Step)
50
-
51
- ### Step 1: Clone the repo
52
-
53
- ```bash
54
- git clone https://github.com/kodelyx/flow-agent.git
55
- cd flow-agent
56
- ```
57
-
58
- ### Step 2: Install Python dependencies
59
-
60
- ```bash
61
- pip install -r requirements.txt
62
- ```
63
-
64
- This installs `websockets`, `opencv-python-headless`, and `numpy`.
65
-
66
- ### Step 3: Install the Chrome Extension
67
-
68
- 1. Open Chrome browser
69
- 2. Go to `chrome://extensions` in the address bar
70
- 3. Toggle **"Developer mode"** ON (top-right corner)
71
- 4. Click **"Load unpacked"**
72
- 5. Select the `extension/` folder from this repo
73
- 6. You should see the **Flow Agent** extension appear
74
-
75
- ### Step 4: Open Google Flow
76
-
77
- 1. Open [labs.google/fx/tools/flow](https://labs.google/fx/tools/flow) in Chrome
78
- 2. Make sure you're **logged into your Google account**
79
- 3. The extension icon should show a **green badge** = connected
80
- 4. The extension auto-opens this tab when needed
81
-
82
- > ⚠️ The Flow tab auto-opens when you run a command. No manual tab management needed!
83
-
84
- ---
85
-
86
- ## 🚀 Usage
87
-
88
- ### Text → Video (T2V)
89
-
90
- Generate a new video from a text description.
91
-
92
- ```bash
93
- # Basic (portrait 9:16, 10 seconds)
94
- python -m cli.generate "A samurai drawing his katana on a cliff at golden sunset"
95
-
96
- # Landscape mode (16:9)
97
- python -m cli.generate "Eagle soaring over snowy mountains" --aspect landscape
98
-
99
- # Custom output file
100
- python -m cli.generate "A dragon breathing fire" -o dragon.mp4
101
-
102
- # Shorter duration (4/6/8/10 seconds)
103
- python -m cli.generate "Dog playing in the park" --duration 6
104
-
105
- # Generate multiple variations
106
- python -m cli.generate "Cyberpunk city at night" --count 4
107
-
108
- # I2V — animate a still image
109
- python -m cli.generate "Character comes alive" --start photo.png
110
-
111
- # FL — First + Last frame (controlled transition)
112
- python -m cli.generate "Person walks forward" --start start.png --end end.png
113
-
114
- # R2V — Reference images (character consistency)
115
- python -m cli.generate "Character in new scene" --ref char1.png char2.png
116
- ```
117
-
118
- **CLI Options:**
119
- | Flag | Short | Default | Description |
120
- |------|-------|---------|-------------|
121
- | `--output` | `-o` | `omni_output.mp4` | Output filename |
122
- | `--aspect` | `-a` | `portrait` | `portrait` or `landscape` |
123
- | `--duration` | `-d` | `10` | `4`, `6`, `8`, or `10` seconds |
124
- | `--count` | `-c` | `1` | Generate 1-4 videos |
125
- | `--edit` | `-e` | - | Pass media_id for V2V edit mode |
126
- | `--start` | `-s` | - | Start frame image (I2V / FL mode) |
127
- | `--end` | | - | End frame image (use with --start for FL) |
128
- | `--ref` | `-r` | - | Reference image(s) for R2V mode |
129
- | `--no-clean` | | - | Skip auto watermark removal |
130
-
131
- ---
132
-
133
- ### Text → Image (T2I)
134
-
135
- Generate images from a text description.
136
-
137
- ```bash
138
- # Basic (portrait 9:16)
139
- python -m cli.image "A dragon breathing fire in a cyberpunk city"
140
-
141
- # Landscape
142
- python -m cli.image "Mountain sunset" --aspect landscape -o sunset.png
143
-
144
- # Square (for logos, icons)
145
- python -m cli.image "Minimal logo design" --aspect square
146
-
147
- # Generate 4 variations
148
- python -m cli.image "Abstract art" --count 4
149
-
150
- # I2I: Edit with reference image
151
- python -m cli.image "Make it anime style" --ref original.png -o anime.png
152
- ```
153
-
154
- **CLI Options:**
155
- | Flag | Short | Default | Description |
156
- |------|-------|---------|-------------|
157
- | `--output` | `-o` | `output/image.png` | Output filename |
158
- | `--aspect` | `-a` | `portrait` | `portrait`, `landscape`, `square`, `4x3`, `3x4` |
159
- | `--count` | `-c` | `1` | Generate 1-4 variations |
160
- | `--ref` | `-r` | - | Reference image(s) for I2I |
161
-
162
- ### Upload Video
163
-
164
- Upload a local video to Google Flow. Returns a `media_id` needed for V2V editing.
165
-
166
- ```bash
167
- # Single video
168
- python -m cli.upload my_video.mp4
169
-
170
- # Batch upload all .mp4 in a folder
171
- python -m cli.upload chunks/ --batch
172
- ```
173
-
174
- The `media_id` is **automatically saved** to `media-id.js`:
175
- ```
176
- my_video.mp4 : 49f7d936-01e3-41ad-917a-2f9bb6ead00b
177
- ```
178
-
179
- ---
180
-
181
- ### Video → Video Edit (V2V)
182
-
183
- Apply style changes to an uploaded video (e.g., convert to anime).
184
-
185
- ```bash
186
- # Step 1: Upload your video
187
- python -m cli.upload my_video.mp4
188
- # → media_id saved to media-id.js
189
-
190
- # Step 2: Edit with style prompt
191
- python -m cli.edit "Transform into vibrant anime style, Studio Ghibli aesthetic" \
192
- --media-id 49f7d936-01e3-41ad-917a-2f9bb6ead00b \
193
- --video-file my_video.mp4 \
194
- --output output_anime/ \
195
- --merge
196
-
197
- # Without local video file (specify duration manually)
198
- python -m cli.edit "Make it look cyberpunk neon" \
199
- -m MEDIA_ID \
200
- --total-seconds 30 \
201
- -o output_cyber/
202
- ```
203
-
204
- **How it works:** Long videos are automatically split into 10s segments, each processed in parallel, then merged with ffmpeg.
205
-
206
- **CLI Options:**
207
- | Flag | Short | Required | Description |
208
- |------|-------|----------|-------------|
209
- | `--media-id` | `-m` | Yes | Flow media ID (from upload) |
210
- | `--video-file` | `-v` | No | Local file (auto-detects duration/fps) |
211
- | `--total-seconds` | `-t` | No | Duration if no local file |
212
- | `--output` | `-o` | No | Output directory (default: `output/`) |
213
- | `--aspect` | `-a` | No | `portrait` or `landscape` |
214
- | `--merge` | | No | Merge segments with ffmpeg |
215
-
216
- ---
217
-
218
- ### Image → Video (I2V)
219
-
220
- Animate a still image into a video. Requires Python scripting (no CLI yet):
221
-
222
- ```python
223
- import asyncio
224
- from omniflash import (
225
- ExtensionBridge, upload_image, generate_video_i2v,
226
- poll_status, download_video, ASPECTS, DEFAULT_PROJECT,
227
- )
228
-
229
- async def main():
230
- # Connect to extension
231
- bridge = ExtensionBridge()
232
- await bridge.start()
233
- await bridge.wait_for_extension(30)
234
-
235
- # Upload your image
236
- img_id = await upload_image(bridge, "my_image.png")
237
- print(f"Image uploaded: {img_id}")
238
-
239
- # Generate video from image
240
- media_ids = await generate_video_i2v(
241
- bridge,
242
- prompt="The character comes alive, dramatic movement, cinematic",
243
- aspect=ASPECTS['portrait'], # or ASPECTS['landscape']
244
- project_id=DEFAULT_PROJECT,
245
- image_media_id=img_id,
246
- duration=8, # 4, 6, 8, or 10 seconds
247
- )
248
-
249
- # Wait for video to finish
250
- if media_ids:
251
- await poll_status(bridge, media_ids[0], DEFAULT_PROJECT)
252
- await download_video(bridge, media_ids[0], "output_i2v.mp4")
253
-
254
- await bridge.close()
255
-
256
- asyncio.run(main())
257
- ```
258
-
259
- ---
260
-
261
- ### API Sniffer
262
-
263
- Capture all API requests made by the Flow UI. Useful for discovering new endpoints or debugging.
264
-
265
- ```bash
266
- # Start sniffer, then use Flow UI normally
267
- python -m cli.sniff
268
-
269
- # Save captured requests to file
270
- python -m cli.sniff --save sniffed.json
271
- ```
272
-
273
- See [SNIFFING.md](SNIFFING.md) for the full API discovery guide.
274
-
275
- ---
276
-
277
- ## 🌐 HTTP/HTTPS API Server (for n8n & external integrations)
278
-
279
- A FastAPI-based API server is included to trigger all Flow Agent features remotely (e.g., from n8n HTTP Request nodes, custom webhooks, or automation workflows).
280
-
281
- ### Start the API Server
282
-
283
- Run the server from the project directory:
284
- ```bash
285
- # Standard HTTP (defaults to port 8000)
286
- venv/bin/python -m cli.api --host 0.0.0.0 --port 8000
287
-
288
- # Optional HTTPS (auto-generates self-signed SSL certificates)
289
- venv/bin/python -m cli.api --host 0.0.0.0 --port 8443 --ssl
290
- ```
291
-
292
- ### Core API Endpoints
293
-
294
- | Method | Endpoint | Description |
295
- |--------|----------|-------------|
296
- | **GET** | `/health` | Check Extension Bridge health and token status. |
297
- | **POST** | `/generate/video` | T2V, I2V, FL, R2V video generation. Supports query `?download=true` to stream the binary `.mp4` file. |
298
- | **POST** | `/generate/image` | T2I, I2I image generation. Supports `?download=true` to stream the binary `.png` file. |
299
- | **POST** | `/upload/image` | Upload an image to Flow (via file upload or local file path). |
300
- | **POST** | `/upload/video` | Upload a video to Flow (via file upload or local file path). |
301
- | **POST** | `/edit/video` | V2V video editing (restyling segment duration). |
302
- | **GET** | `/download/{filename}` | Download generated image/video files from the `output/` folder. |
303
-
304
- ### Verify with Integration Tests
305
-
306
- A comprehensive integration test script is provided to verify all endpoints:
307
- ```bash
308
- venv/bin/python test_api.py
309
- ```
310
-
311
- See [error.md](error.md) for detailed troubleshooting instructions if you encounter port conflicts or proxy network issues.
312
-
313
- ---
314
-
315
- ## 🐍 Python API (for developers)
316
-
317
- Use the `omniflash` package directly in your own scripts:
318
-
319
- ```python
320
- from omniflash import (
321
- ExtensionBridge, # WebSocket bridge to Chrome extension
322
- generate_video, # T2V: text → video
323
- edit_video, # V2V: video → video
324
- upload_image, # Upload image → get media_id
325
- generate_video_i2v, # I2V: image → video
326
- poll_status, # Poll until video is ready
327
- download_video, # Download finished video
328
- ASPECTS, # {'portrait': '...', 'landscape': '...'}
329
- DEFAULT_PROJECT, # Your default project ID
330
- )
331
- from omniflash.upload import upload_video # Upload video file
332
- from omniflash import media_store # Read/write media-id.js
333
-
334
- # media_store examples:
335
- media_store.save("video.mp4", "uuid-here") # Save entry
336
- mid = media_store.get("video.mp4") # Get media_id
337
- all_entries = media_store.read_entries() # Get all entries
338
- ```
339
-
340
- > **Backward compatible:** `from omni import ExtensionBridge, generate_video, ...` still works.
341
-
342
- ---
343
-
344
- ## 📁 Project Structure
345
-
346
- ```
347
- flow-agent/
348
- ├── omniflash/ # Core Python package
349
- │ ├── __init__.py # Public API exports
350
- │ ├── bridge.py # ExtensionBridge (WS + HTTP + auto-retry)
351
- │ ├── config.py # All config hardcoded here
352
- │ ├── media_store.py # media-id.js read/write
353
- │ ├── upload.py # Video upload (GCS resumable)
354
- │ ├── watermark.py # Auto watermark removal (embedded assets)
355
- │ └── generators/ # API functions
356
- │ ├── common.py # poll_status, download_video
357
- │ ├── t2v.py # Text → Video
358
- │ ├── t2i.py # Text → Image + I2I
359
- │ ├── v2v.py # Video → Video (edit)
360
- │ └── i2v.py # Image → Video + upload_image
361
- ├── cli/ # CLI entry points
362
- │ ├── generate.py # python -m cli.generate
363
- │ ├── image.py # python -m cli.image
364
- │ ├── upload.py # python -m cli.upload
365
- │ ├── edit.py # python -m cli.edit
366
- │ └── sniff.py # python -m cli.sniff
367
- ├── extension/ # Chrome extension
368
- │ ├── manifest.json # Extension manifest
369
- │ ├── background.js # WS client, API proxy
370
- │ ├── content.js # Page ↔ background bridge
371
- │ └── injected.js # Fetch interceptor, reCAPTCHA
372
- ├── omni.py # Backward-compatible wrapper
373
- ├── .gitignore # Git ignore rules
374
- ├── media-id.js # Auto-updated filename → media_id
375
- ├── requirements.txt # Python dependencies
376
- ├── SNIFFING.md # API discovery guide
377
- └── README.md
378
- ```
379
-
380
- ---
381
-
382
- ## ⚙️ How It Works
383
-
384
- ```
385
- ┌─────────────────────────────────┐
386
- │ Your Terminal / Python Script │
387
- │ python -m cli.generate "..." │
388
- └──────────┬──────────────────────┘
389
- │ import omniflash
390
- ▼
391
- ┌─────────────────────────────────┐
392
- │ omniflash package │
393
- │ ExtensionBridge (WS + HTTP) │
394
- └──────────┬──────────────────────┘
395
- │ WebSocket (:9222)
396
- │ HTTP callback (:8100)
397
- ▼
398
- ┌─────────────────────────────────┐
399
- │ Chrome Extension (Flow Agent) │
400
- │ Auth token + reCAPTCHA solving │
401
- └──────────┬──────────────────────┘
402
- │ HTTPS (browser cookies)
403
- ▼
404
- ┌─────────────────────────────────┐
405
- │ Google Omni API (aisandbox) │
406
- │ Video generation / editing │
407
- └─────────────────────────────────┘
408
- ```
409
-
410
- 1. Python starts a WebSocket server + HTTP callback server
411
- 2. Chrome extension auto-connects and provides authentication
412
- 3. Script sends API requests through the extension
413
- 4. Extension solves reCAPTCHA and proxies with browser cookies
414
- 5. Script polls for completion, then downloads the result
415
-
416
- ---
417
-
418
- ## 🎯 Models & Endpoints
419
-
420
- | Model | Key | Duration | Type |
421
- |-------|-----|----------|------|
422
- | Omni Flash T2V 4s | `abra_t2v_4s` | 4 sec | Text → Video |
423
- | Omni Flash T2V 6s | `abra_t2v_6s` | 6 sec | Text → Video |
424
- | Omni Flash T2V 8s | `abra_t2v_8s` | 8 sec | Text → Video |
425
- | Omni Flash T2V 10s | `abra_t2v_10s` | 10 sec | Text → Video |
426
- | Omni Flash Edit | `abra_edit` | 10 sec | Video → Video |
427
-
428
- | Endpoint | Path |
429
- |----------|------|
430
- | T2V | `/v1/video:batchAsyncGenerateVideoText` |
431
- | I2V | `/v1/video:batchAsyncGenerateVideoStartImage` |
432
- | V2V Edit | `/v1/video:batchAsyncGenerateVideoEditVideo` |
433
- | Upload Image | `/v1/flow/uploadImage` |
434
- | Poll Status | `/v1/video:batchCheckAsyncVideoGenerationStatus` |
435
- | Get Media | `/v1/video/media/{media_id}` |
436
-
437
- ---
438
-
439
- ## 🔧 Troubleshooting
440
-
441
- | Problem | Solution |
442
- |---------|----------|
443
- | Extension not connecting | Make sure Flow tab is open and you're logged in |
444
- | `Address already in use` | Another script is using port 9222/8100. Kill it first |
445
- | `TIMEOUT` error | Extension may have disconnected. Reload Flow tab |
446
- | `reCAPTCHA failed` | Reload Flow tab, wait a few seconds, try again |
447
- | `No media in response` | Check your prompt. Some prompts get blocked |
448
- | `curl failed` | Upload too large or network issue. Retry |
449
- | Video quality poor | Use longer duration (10s) and detailed prompts |
450
- | V2V merge fails | Install ffmpeg: `brew install ffmpeg` |
451
-
452
- ---
453
-
454
- ## ⚠️ Important Notes
455
-
456
- - **Flow tab auto-opens** — no manual tab management needed
457
- - Uses your Google account's **free Flow credits** (check remaining in Flow UI)
458
- - Extension auto-reconnects and auto-retries (3 attempts)
459
- - **Watermark auto-removed** on every generated video (~1s)
460
- - `media-id.js` auto-updates on every upload (video or image)
461
- - All generated videos save to the `output/` directory by default
462
- - Old `from omni import ...` syntax still works (backward compatible)
463
-
464
- ---
465
-
466
- ## 📄 License
467
-
468
- MIT
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
flow-agent/SNIFFING.md DELETED
@@ -1,205 +0,0 @@
1
- # 🔍 API Sniffing Guide
2
-
3
- How to discover new Google Flow API endpoints using the Chrome extension's built-in request sniffer.
4
-
5
- ## How It Works
6
-
7
- ```
8
- Flow UI (browser)
9
- ↓ user clicks "Generate" / "Upload" etc.
10
- ↓
11
- fetch() call to aisandbox-pa.googleapis.com
12
- ↓ intercepted by injected.js (monkey-patched fetch)
13
- ↓
14
- postMessage → content.js → background.js
15
- ↓
16
- HTTP POST → http://127.0.0.1:8100/api/ext/callback
17
- ↓
18
- Your sniff server logs the URL + payload
19
- ```
20
-
21
- The extension's `injected.js` monkey-patches `window.fetch` to intercept ALL outgoing requests to `aisandbox-pa.googleapis.com`. Every request's URL, method, and body are forwarded to your local server.
22
-
23
- ## Quick Start
24
-
25
- ### 1. Start the Sniff Server
26
-
27
- ```python
28
- python sniff.py
29
- ```
30
-
31
- This starts:
32
- - WebSocket server on `ws://127.0.0.1:9222` (extension connects here)
33
- - HTTP server on `http://127.0.0.1:8100` (receives sniffed data)
34
-
35
- ### 2. Open Flow UI
36
-
37
- Go to [labs.google/fx/tools/flow](https://labs.google/fx/tools/flow) in Chrome.
38
- The extension will auto-connect to your sniff server.
39
-
40
- ### 3. Perform the Action
41
-
42
- Do whatever you want to discover the API for:
43
- - Upload an image/video
44
- - Generate a video
45
- - Change settings
46
- - Click any button
47
-
48
- ### 4. Read the Logs
49
-
50
- The sniff server prints every intercepted request:
51
- ```
52
- 🔍 SNIFFED: https://aisandbox-pa.googleapis.com/v1/video:batchAsyncGenerateVideoText
53
- Method: POST
54
- Payload: {"mediaGenerationContext":{"batchId":"..."},"clientContext":{...},"requests":[...]}
55
- ```
56
-
57
- ## Sniff Server Code
58
-
59
- Save this as `sniff.py`:
60
-
61
- ```python
62
- #!/usr/bin/env python3
63
- """Sniff server — captures all Flow UI API requests."""
64
-
65
- import asyncio, json, websockets, logging
66
- from http.server import HTTPServer, BaseHTTPRequestHandler
67
- import threading
68
-
69
- logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s', datefmt='%H:%M:%S')
70
- log = logging.getLogger('sniff')
71
-
72
- # Store all sniffed requests
73
- all_requests = []
74
-
75
- class Handler(BaseHTTPRequestHandler):
76
- def do_POST(self):
77
- length = int(self.headers.get('Content-Length', 0))
78
- body = json.loads(self.rfile.read(length)) if length else {}
79
-
80
- if body.get('type') == 'sniffed_video_request':
81
- url = body.get('url', '')
82
- method = body.get('method', '?')
83
- payload = body.get('payload', '')
84
-
85
- log.info('🔍 %s %s', method, url)
86
- if payload:
87
- log.info(' %s', str(payload)[:1000])
88
-
89
- all_requests.append({
90
- 'url': url,
91
- 'method': method,
92
- 'payload': payload,
93
- 'timestamp': body.get('timestamp'),
94
- })
95
-
96
- self.send_response(200)
97
- self.send_header('Content-Type', 'application/json')
98
- self.send_header('Access-Control-Allow-Origin', '*')
99
- self.end_headers()
100
- self.wfile.write(b'{"ok":true}')
101
-
102
- def do_OPTIONS(self):
103
- self.send_response(200)
104
- self.send_header('Access-Control-Allow-Origin', '*')
105
- self.send_header('Access-Control-Allow-Methods', 'POST')
106
- self.send_header('Access-Control-Allow-Headers', 'Content-Type')
107
- self.end_headers()
108
-
109
- def log_message(self, *a): pass
110
-
111
- # Start HTTP server
112
- srv = HTTPServer(('127.0.0.1', 8100), Handler)
113
- threading.Thread(target=srv.serve_forever, daemon=True).start()
114
- log.info('HTTP callback on :8100')
115
-
116
- async def on_connect(ws):
117
- log.info('✅ Extension connected!')
118
- async for raw in ws:
119
- data = json.loads(raw)
120
- if data.get('type') == 'token_captured':
121
- log.info('🔑 Token captured')
122
-
123
- async def main():
124
- async with websockets.serve(on_connect, '127.0.0.1', 9222):
125
- log.info('⚡ WS server on :9222')
126
- log.info('👉 Open Flow UI and perform any action...')
127
- await asyncio.Future()
128
-
129
- asyncio.run(main())
130
- ```
131
-
132
- ## What Gets Captured
133
-
134
- | Action in Flow UI | API Endpoint |
135
- |-------------------|-------------|
136
- | Generate video (T2V) | `/v1/video:batchAsyncGenerateVideoText` |
137
- | Generate video (I2V) | `/v1/video:batchAsyncGenerateVideoStartImage` |
138
- | Generate video (Edit) | `/v1/video:batchAsyncGenerateVideoEditVideo` |
139
- | Poll video status | `/v1/video:batchCheckAsyncVideoGenerationStatus` |
140
- | Upload image | `/v1/flow/uploadImage` |
141
- | Generate image | `/v1/projects/{id}/flowMedia:batchGenerateImages` |
142
- | Get credits | `/v1/credits` |
143
- | Get media | `/v1/media/{media_id}` |
144
- | Upscale video | `/v1/video:batchAsyncGenerateVideoUpsampleVideo` |
145
-
146
- ## How to Find New Endpoints
147
-
148
- ### Example: Finding Video Upload
149
-
150
- 1. Start `sniff.py`
151
- 2. Open Flow UI
152
- 3. Drag & drop a video file into Flow
153
- 4. Check logs — you'll see the upload URL and payload format
154
- 5. Add the new endpoint to `models.json`
155
-
156
- ### Example: Finding Model Keys
157
-
158
- 1. Start `sniff.py`
159
- 2. Open Flow UI
160
- 3. Select different model (e.g., Omni Flash 4s)
161
- 4. Click Generate
162
- 5. Check logs — look for `videoModelKey` in the payload
163
-
164
- ```json
165
- "requests": [{
166
- "videoModelKey": "abra_t2v_4s", ← this is what you need
167
- ...
168
- }]
169
- ```
170
-
171
- ## Architecture
172
-
173
- ```
174
- ┌─────────────────────────────────────────────┐
175
- │ injected.js (MAIN world) │
176
- │ - Monkey-patches window.fetch │
177
- │ - Captures URL + body of every request │
178
- │ - Posts to content.js via postMessage │
179
- └──────────────────┬──────────────────────────┘
180
- │ postMessage
181
- ┌──────────────────▼──────────────────────────┐
182
- │ content.js (ISOLATED world) │
183
- │ - Listens for __FLOWKIT_SNIFF__ messages │
184
- │ - Forwards to background.js │
185
- └──────────────────┬──────────────────────────┘
186
- │ chrome.runtime.sendMessage
187
- ┌──────────────────▼──────────────────────────┐
188
- │ background.js (Service Worker) │
189
- │ - Receives SNIFFED_AISANDBOX_REQUEST │
190
- │ - POSTs to http://127.0.0.1:8100/callback │
191
- └──────────────────┬──────────────────────────┘
192
- │ HTTP POST
193
- ┌──────────────────▼──────────────────────────┐
194
- │ sniff.py (Your server) │
195
- │ - Logs every request │
196
- │ - Saves URL + method + payload │
197
- └─────────────────────────────────────────────┘
198
- ```
199
-
200
- ## Tips
201
-
202
- - **Filter by keyword**: Modify the sniff server to only log URLs containing specific words (e.g., `upload`, `video`, `generate`)
203
- - **Save to file**: Add `json.dump(all_requests, open('sniffed.json', 'w'))` to save all captured requests
204
- - **Compare payloads**: Run the same action with different settings and diff the payloads to find which fields control what
205
- - **Telemetry noise**: Ignore URLs containing `batchLog`, `fetchUserRecommendations`, `frontendEvents` — these are analytics, not API calls
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
flow-agent/error.md DELETED
@@ -1,74 +0,0 @@
1
- # 🛠️ Flow Agent API Troubleshooting Guide (error.md)
2
-
3
- This document contains standard error scenarios and how to resolve them quickly.
4
-
5
- ---
6
-
7
- ## 1. Error: `OSError: [Errno 48] Address already in use`
8
- * **Symptom**: The server fails to start and exits with: `OSError: [Errno 48] Address already in use` (typically for port `8000`, `8100`, or `9222`).
9
- * **Cause**: Another instance of the API server or a background flow-agent process is already running and occupying the port.
10
- * **Resolution**:
11
- Run the following commands in your terminal to find and kill the process:
12
- ```bash
13
- # Clear API server port (8000)
14
- kill -9 $(lsof -t -i:8000) 2>/dev/null || true
15
-
16
- # Clear Extension bridge HTTP callback port (8100)
17
- kill -9 $(lsof -t -i:8100) 2>/dev/null || true
18
-
19
- # Clear Extension bridge WebSocket port (9222)
20
- kill -9 $(lsof -t -i:9222) 2>/dev/null || true
21
- ```
22
-
23
- ---
24
-
25
- ## 2. Error: `Internal Server Error (500) - RuntimeError: curl failed`
26
- * **Symptom**: Step `Uploading Video to Flow` fails with Status Code `500` and the server console prints: `RuntimeError: curl failed: ...`
27
- * **Cause**: Your terminal session has sandbox/proxy environment variables active (`http_proxy`, `https_proxy`, `HTTP_PROXY`, or `HTTPS_PROXY` might be set by the AI agent sandbox). This causes `curl` to route all Google Cloud Storage uploads through a proxy that blocks the connection.
28
- * **Resolution**:
29
- Clear the proxy variables in your terminal window before starting the server and running the test script:
30
- ```bash
31
- # 1. Unset the proxy variables
32
- unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY
33
-
34
- # 2. Restart the API server in this terminal
35
- venv/bin/python -m cli.api --port 8000
36
- ```
37
- *(Make sure to also run `unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY` in your testing/client terminal window as well).*
38
-
39
- ---
40
-
41
- ## 3. Error: `Google Flow extension is not connected or unauthorized`
42
- * **Symptom**: `/health` returns `has_flow_key: false` and generation calls return: `"Google Flow extension is not connected or unauthorized. Make sure Google Flow tab is open in Chrome."`
43
- * **Cause**: The Extension Bridge WS is connected, but the Chrome extension is unable to capture the auth token (`flowKey`) because Google Flow is either not open, has gone idle, or your Google account has logged out.
44
- * **Resolution**:
45
- 1. Open Chrome.
46
- 2. Make sure you are logged into your Google account at **[labs.google/fx/tools/flow](https://labs.google/fx/tools/flow)**.
47
- 3. Reload the page. The extension icon in your extension bar should show a green indicator.
48
- 4. Once logged in, the extension will automatically push the token to the server and heal the state.
49
-
50
- ---
51
-
52
- ## 4. Error: `Failed (0): TIMEOUT`
53
- * **Symptom**: Request fails after 90 seconds with `TIMEOUT`.
54
- * **Cause**: Google Flow took too long to respond, or there is an active **reCAPTCHA challenge** popped up on your Chrome browser that requires manual verification.
55
- * **Resolution**:
56
- 1. Open Chrome and inspect the Google Flow tab.
57
- 2. If a reCAPTCHA prompt is present, solve it.
58
- 3. Reload the tab to refresh the connection, wait 5 seconds, and try your request again.
59
-
60
- ---
61
-
62
- ## 5. Error: `zsh: no such file or directory: venv/bin/python`
63
- * **Symptom**: Running server or test script returns: `zsh: no such file or directory: venv/bin/python` or similar file errors.
64
- * **Cause**: The command is run from the parent workspace folder (`N8N-Agent`) instead of the cloned `flow-agent` project folder where the virtual environment (`venv`) resides.
65
- * **Resolution**:
66
- Always change your directory to the `flow-agent` folder before running commands, or use the absolute paths:
67
- ```bash
68
- # Go to the correct directory first
69
- cd /path/to/flow-agent
70
-
71
- # Then run the command
72
- venv/bin/python -m cli.api --port 8000
73
- ```
74
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
flow-agent/test_api.py DELETED
@@ -1,319 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Integration Test Script for Flow Agent API.
3
-
4
- Tests the following end-to-end flow:
5
- 1. GET /health
6
- 2. POST /generate/image (T2I)
7
- 3. POST /upload/image
8
- 4. POST /generate/video (I2V)
9
- 5. POST /upload/video
10
- 6. POST /edit/video (V2V)
11
- """
12
-
13
- import os
14
- import sys
15
- import time
16
-
17
- # Add virtual environment site-packages to sys.path to run with system python
18
- venv_site_packages = os.path.join(os.path.dirname(os.path.abspath(__file__)), "venv", "lib", "python3.14", "site-packages")
19
- if os.path.exists(venv_site_packages):
20
- sys.path.insert(0, venv_site_packages)
21
-
22
- # Clear proxy environment variables to bypass sandbox proxy for local requests
23
- os.environ.pop("HTTP_PROXY", None)
24
- os.environ.pop("HTTPS_PROXY", None)
25
- os.environ.pop("http_proxy", None)
26
- os.environ.pop("https_proxy", None)
27
-
28
- # Auto-install requests if not present
29
- try:
30
- import requests
31
- except ImportError:
32
- print("📦 Installing 'requests' library for testing...")
33
- os.system(f"{sys.executable} -m pip install requests")
34
- import requests
35
-
36
- API_URL = "http://localhost:8000"
37
-
38
- def log_step(name):
39
- print(f"\n{'=' * 60}")
40
- print(f"🚀 STEP: {name}")
41
- print(f"{'=' * 60}")
42
-
43
- def check_health():
44
- log_step("Checking Server Health")
45
- try:
46
- r = requests.get(f"{API_URL}/health")
47
- print(f"Status Code: {r.status_code}")
48
- print(f"Response: {r.text}")
49
- if r.status_code != 200:
50
- print("❌ Server health check failed!")
51
- sys.exit(1)
52
- data = r.json()
53
- if not data.get("extension_connected"):
54
- print("❌ Chrome extension is NOT connected. Please check Chrome devtools.")
55
- sys.exit(1)
56
- if not data.get("has_flow_key"):
57
- print("⚠️ Chrome extension is connected but NOT logged in / authorized.")
58
- print(" Please make sure labs.google/fx/tools/flow is open and logged in Chrome.")
59
- sys.exit(1)
60
- print("✅ Health Check Passed!")
61
- except Exception as e:
62
- print(f"❌ Failed to connect to server: {e}")
63
- sys.exit(1)
64
-
65
- def generate_image():
66
- log_step("Text-to-Image (T2I) Generation")
67
- payload = {
68
- "prompt": "a simple red apple on a clean wooden table, professional studio lighting, 8k resolution",
69
- "aspect": "square",
70
- "count": 1
71
- }
72
- r = requests.post(f"{API_URL}/generate/image", json=payload)
73
- print(f"Status Code: {r.status_code}")
74
- print(f"Response: {r.text}")
75
-
76
- if r.status_code != 200:
77
- print("❌ Image generation failed!")
78
- sys.exit(1)
79
-
80
- data = r.json()
81
- outputs = data.get("outputs", [])
82
- if not outputs:
83
- print("❌ No outputs returned in image generation!")
84
- sys.exit(1)
85
-
86
- img_info = outputs[0]
87
- remote_url = img_info.get("remote_url")
88
- filename = img_info.get("filename")
89
-
90
- # Download generated image locally for next steps
91
- local_img_path = os.path.join("output", "test_t2i.png")
92
- os.makedirs("output", exist_ok=True)
93
-
94
- print(f"📥 Downloading image from {remote_url}...")
95
- img_r = requests.get(remote_url)
96
- with open(local_img_path, "wb") as f:
97
- f.write(img_r.content)
98
-
99
- print(f"✅ Saved test image to {local_img_path}")
100
- return local_img_path
101
-
102
- def upload_image(image_path):
103
- log_step("Uploading Image to Flow")
104
- with open(image_path, "rb") as f:
105
- files = {"file": (os.path.basename(image_path), f, "image/png")}
106
- r = requests.post(f"{API_URL}/upload/image", files=files)
107
-
108
- print(f"Status Code: {r.status_code}")
109
- print(f"Response: {r.text}")
110
-
111
- if r.status_code != 200:
112
- print("❌ Image upload failed!")
113
- sys.exit(1)
114
-
115
- data = r.json()
116
- media_id = data.get("media_id")
117
- if not media_id:
118
- print("❌ No media_id returned from upload!")
119
- sys.exit(1)
120
-
121
- print(f"✅ Image uploaded successfully! media_id: {media_id}")
122
- return media_id
123
-
124
- def generate_image_i2i(image_media_id):
125
- log_step("Image-to-Image (I2I) Generation")
126
- payload = {
127
- "prompt": "transform the red apple into a vibrant cartoon style, Pixar 3D aesthetic",
128
- "aspect": "square",
129
- "count": 1,
130
- "ref": [image_media_id]
131
- }
132
- r = requests.post(f"{API_URL}/generate/image", json=payload)
133
- print(f"Status Code: {r.status_code}")
134
- print(f"Response: {r.text}")
135
-
136
- if r.status_code != 200:
137
- print("❌ Image-to-Image (I2I) generation failed!")
138
- sys.exit(1)
139
-
140
- data = r.json()
141
- outputs = data.get("outputs", [])
142
- if not outputs:
143
- print("❌ No outputs returned in I2I generation!")
144
- sys.exit(1)
145
-
146
- img_info = outputs[0]
147
- remote_url = img_info.get("remote_url")
148
-
149
- local_i2i_path = os.path.join("output", "test_i2i.png")
150
- print(f"📥 Downloading I2I image from {remote_url}...")
151
- img_r = requests.get(remote_url)
152
- with open(local_i2i_path, "wb") as f:
153
- f.write(img_r.content)
154
-
155
- print(f"✅ Saved I2I image to {local_i2i_path}")
156
- return local_i2i_path
157
-
158
- def generate_video_t2v():
159
- log_step("Text-to-Video (T2V) Generation")
160
- payload = {
161
- "prompt": "a beautiful golden retriever playing in a park, high quality, 8k, cinematic lighting",
162
- "aspect": "portrait",
163
- "duration": 4,
164
- "count": 1
165
- }
166
- r = requests.post(f"{API_URL}/generate/video", json=payload)
167
- print(f"Status Code: {r.status_code}")
168
- print(f"Response: {r.text}")
169
-
170
- if r.status_code != 200:
171
- print("❌ T2V video generation failed!")
172
- sys.exit(1)
173
-
174
- data = r.json()
175
- outputs = data.get("outputs", [])
176
- if not outputs:
177
- print("❌ No outputs returned in T2V video generation!")
178
- sys.exit(1)
179
-
180
- video_info = outputs[0]
181
- download_url = video_info.get("download_url")
182
-
183
- local_video_path = os.path.join("output", "test_t2v.mp4")
184
-
185
- print(f"📥 Downloading video from {API_URL}{download_url}...")
186
- video_r = requests.get(f"{API_URL}{download_url}")
187
- with open(local_video_path, "wb") as f:
188
- f.write(video_r.content)
189
-
190
- print(f"✅ Saved T2V video to {local_video_path}")
191
- return local_video_path
192
-
193
- def generate_video_i2v(image_media_id):
194
- log_step("Image-to-Video (I2V) Generation")
195
- payload = {
196
- "prompt": "the apple slowly rolls forward, dynamic cinematic panning, highly realistic",
197
- "aspect": "portrait",
198
- "duration": 4, # Short duration for faster testing
199
- "count": 1,
200
- "start": image_media_id # Animate using the uploaded image
201
- }
202
- r = requests.post(f"{API_URL}/generate/video", json=payload)
203
- print(f"Status Code: {r.status_code}")
204
- print(f"Response: {r.text}")
205
-
206
- if r.status_code != 200:
207
- print("❌ Video generation failed!")
208
- sys.exit(1)
209
-
210
- data = r.json()
211
- outputs = data.get("outputs", [])
212
- if not outputs:
213
- print("❌ No outputs returned in video generation!")
214
- sys.exit(1)
215
-
216
- video_info = outputs[0]
217
- download_url = video_info.get("download_url")
218
- filename = video_info.get("filename")
219
-
220
- local_video_path = os.path.join("output", "test_i2v.mp4")
221
-
222
- print(f"📥 Downloading video from {API_URL}{download_url}...")
223
- video_r = requests.get(f"{API_URL}{download_url}")
224
- with open(local_video_path, "wb") as f:
225
- f.write(video_r.content)
226
-
227
- print(f"✅ Saved test video to {local_video_path}")
228
- return local_video_path
229
-
230
- def upload_video(video_path):
231
- log_step("Uploading Video to Flow")
232
- with open(video_path, "rb") as f:
233
- files = {"file": (os.path.basename(video_path), f, "video/mp4")}
234
- r = requests.post(f"{API_URL}/upload/video", files=files)
235
-
236
- print(f"Status Code: {r.status_code}")
237
- print(f"Response: {r.text}")
238
-
239
- if r.status_code != 200:
240
- print("❌ Video upload failed!")
241
- sys.exit(1)
242
-
243
- data = r.json()
244
- media_id = data.get("media_id")
245
- if not media_id:
246
- print("❌ No media_id returned from upload!")
247
- sys.exit(1)
248
-
249
- print(f"✅ Video uploaded successfully! media_id: {media_id}")
250
- return media_id
251
-
252
- def edit_video_v2v(video_media_id):
253
- log_step("Video-to-Video (V2V) Editing")
254
- payload = {
255
- "prompt": "make it look like an anime sketch style, drawing pencil style",
256
- "video_media_id": video_media_id,
257
- "aspect": "portrait",
258
- "fps": 24,
259
- "duration": 4
260
- }
261
- r = requests.post(f"{API_URL}/edit/video", json=payload)
262
- print(f"Status Code: {r.status_code}")
263
- print(f"Response: {r.text}")
264
-
265
- if r.status_code != 200:
266
- print("❌ V2V video editing failed!")
267
- sys.exit(1)
268
-
269
- data = r.json()
270
- outputs = data.get("outputs", [])
271
- if not outputs:
272
- print("❌ No outputs returned in video edit!")
273
- sys.exit(1)
274
-
275
- video_info = outputs[0]
276
- download_url = video_info.get("download_url")
277
-
278
- local_edit_path = os.path.join("output", "test_v2v.mp4")
279
-
280
- print(f"📥 Downloading edited video from {API_URL}{download_url}...")
281
- video_r = requests.get(f"{API_URL}{download_url}")
282
- with open(local_edit_path, "wb") as f:
283
- f.write(video_r.content)
284
-
285
- print(f"✅ Saved edited video to {local_edit_path}")
286
-
287
- def main():
288
- print("🎬 Starting Flow Agent API Integration Test...")
289
-
290
- # 1. Health check
291
- check_health()
292
-
293
- # 2. Text to Image (T2I)
294
- local_image = generate_image()
295
-
296
- # 2b. Text to Video (T2V)
297
- local_t2v_video = generate_video_t2v()
298
-
299
- # 3. Upload Image to GCS/Flow
300
- image_media_id = upload_image(local_image)
301
-
302
- # 4. Image to Image (I2I)
303
- local_i2i_image = generate_image_i2i(image_media_id)
304
-
305
- # 5. Image to Video (I2V)
306
- local_video = generate_video_i2v(image_media_id)
307
-
308
- # 6. Upload Video to GCS/Flow
309
- video_media_id = upload_video(local_video)
310
-
311
- # 7. Video to Video (V2V)
312
- edit_video_v2v(video_media_id)
313
-
314
- print("\n" + "=" * 60)
315
- print("🎉 ALL TESTS PASSED SUCCESSFULLY! Flow Agent API is 100% verified.")
316
- print("=" * 60)
317
-
318
- if __name__ == "__main__":
319
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
{chatgpt-free-api → free-Chatgpt-api}/.gitignore RENAMED
@@ -11,3 +11,6 @@ debug_poll.json
11
 
12
  # Local Output Files
13
  output/
 
 
 
 
11
 
12
  # Local Output Files
13
  output/
14
+
15
+ # prebuilt linux binary (Docker builds from source)
16
+ *.linux-amd64
{chatgpt-free-api → free-Chatgpt-api}/agent.go RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/api_bridge.go RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/chatgpt.go RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/config.go RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/config.json RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/cookies.go RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/cookies_test.go RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/extension.go RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/go.mod RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/go.sum RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/gpt-extension/background.js RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/gpt-extension/icon128.png RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/gpt-extension/icon16.png RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/gpt-extension/icon48.png RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/gpt-extension/icon_large.png RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/gpt-extension/manifest.json RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/gpt-extension/popup.html RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/gpt-extension/popup.js RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/handlers.go RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/helpers.go RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/main.go RENAMED
File without changes
{chatgpt-free-api → free-Chatgpt-api}/sniff.go RENAMED
File without changes
free-gemini-api/.dockerignore DELETED
@@ -1,8 +0,0 @@
1
- dist/
2
- output/
3
- cookies.json
4
- .env
5
- .git/
6
- .DS_Store
7
- goapi
8
- *.exe
 
 
 
 
 
 
 
 
 
free-gemini-api/Dockerfile DELETED
@@ -1,21 +0,0 @@
1
- # Build stage
2
- FROM golang:1.25-alpine AS builder
3
- WORKDIR /app
4
- COPY go.mod go.sum ./
5
- RUN go mod download
6
- COPY . .
7
- RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o free-gemini-api .
8
-
9
- # Runtime stage
10
- FROM alpine:3.19
11
- RUN apk --no-cache add ca-certificates curl
12
- WORKDIR /app
13
- COPY --from=builder /app/free-gemini-api .
14
- RUN mkdir -p /app/output
15
-
16
- EXPOSE 8000 9226
17
-
18
- ENV WS_PORT="9226" \
19
- PORT="8000"
20
-
21
- CMD ["./free-gemini-api"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
free-gemini-api/README.md DELETED
@@ -1,401 +0,0 @@
1
- <div align="center">
2
-
3
- # 🔓 Free Gemini API
4
-
5
- ### Unleash the Full Power of Google Gemini 3.5 Flash, Imagen 3, and Gemini Video — Completely Free
6
-
7
- [![Go Version](https://img.shields.io/badge/Go-1.21+-00ADD8?style=for-the-badge&logo=go&logoColor=white)](https://go.dev)
8
- [![License](https://img.shields.io/badge/License-MIT-green?style=for-the-badge)](LICENSE)
9
- [![Docker](https://img.shields.io/badge/Docker-Hub-2496ED?style=for-the-badge&logo=docker&logoColor=white)](https://hub.docker.com/r/akashyadav758/free-gemini-api)
10
-
11
- **No API Keys. No Token Costs. No Complex Setup. Zero Watermarks.**
12
-
13
- *A high-performance Go reverse-proxy API server wrapping the consumer Gemini portal (`gemini.google.com`). Access text generation, multi-turn chat, image creation (Imagen 3), video creation (Gemini Video), video-to-video styling, and music generation through a simple unified REST interface.*
14
-
15
- [Architectural Benefits](#-architectural-benefits) • [Key Features](#-key-features) • [Quick Start](#-quick-start) • [API Endpoints](#-api-endpoints) • [SDK Integration](#-sdk-integration) • [Architecture](#-architecture)
16
-
17
- </div>
18
-
19
- ---
20
-
21
- ## 🚀 Architectural Benefits
22
-
23
- This project is engineered to solve the real-world operational challenges of web-scraping and reverse-proxying consumer endpoints, delivering production-grade reliability:
24
-
25
- ### 🎨 In-Place Reverse Alpha-Blending Watermark Remover
26
- Google adds visual watermarks to the bottom-right corner of all generated images and videos. The Go API server includes a highly optimized, fully automated native Go implementation ([gemini/watermark.go](file:///Users/akashyadav/Server/Go-Map/Free-gemini-api/free-gemini-api-kodelyx/gemini/watermark.go)) that executes in-process immediately upon download.
27
- * **The Mathematics:** It reverses the blending equation:
28
- $$\text{watermarked} = \alpha \times \text{logo} + (1 - \alpha) \times \text{original}$$
29
- $${\text{original}} = \frac{\text{watermarked} - \alpha \times \text{logo}}{1 - \alpha}$$
30
- * **Layout Adaptability:** Dynamically identifies coordinates and dimensions based on the file aspect ratio (Portrait `720x1280` maps to a `48px` watermark; standard landscape/large scales dynamically map to a `96px` watermark), yielding perfectly clean, professional-grade media outputs without black borders or distortion.
31
- * **Zero Dependencies:** Completely native—runs without requiring Python 3, `numpy`, or `opencv-python`!
32
-
33
- ### 🔄 403 Forbidden Auto-Redirect Bypasser
34
- Downloading media from Google's content servers (`googleusercontent.com`) directly often results in `403 Forbidden` errors. This client implements a custom redirect follow loop:
35
- * **The Pipeline:** It disables Go's default automatic HTTP redirect handler, manually intercepts HTTP `302/307` locations, and dynamically injects the user's active session cookies on *every* redirect hop (e.g. cross-domain transfers to `lh3.usercontent` and `fife.usercontent`), guaranteeing 100% download success.
36
-
37
- ### 🔌 Zero-Spam Chrome Extension WebSocket Bridge
38
- Keeping cookies updated across server restarts is solved via our lightweight Chrome Extension (`/extension`):
39
- * **One-Shot Sync:** Utilizing a persistent WebSocket connection, the extension instantly syncs active cookies on startup or when the browser detects a change, completely avoiding heavy periodic background alarm polls and preserving laptop battery.
40
-
41
- ### 🔍 Parser-Level Deduplication & Rapid Refusal Detection
42
- * **Deduplication:** The JSON response parser identifies and filters out duplicate image/video references returned by the Gemini consumer API, saving bandwidth and disk space.
43
- * **Refusal Detection:** Recognizes generation limit responses early (e.g., *“I can't create more videos for you today...”*), immediately terminating the long-polling routine and returning structured JSON failures instead of hanging for minutes.
44
-
45
- ---
46
-
47
- ## 🔥 Comparison
48
-
49
- | Feature | Standard Cloud API | **Free Gemini API** |
50
- |:---|:---|:---|
51
- | **Pricing** | Pay per token / image / video | **100% Free** |
52
- | **API Key Required** | Yes | **No** (Uses Cookie Session) |
53
- | **Video Generation** | Highly restricted (Expensive) | **Gemini Video Enabled** (Standard Daily Quota) |
54
- | **Image Generation** | Cost per image | **Imagen 3 Enabled** (Unlimited - Uses Gemini 3.5) |
55
- | **Watermark Removal** | None (Or paid edit) | **Automatic In-Place Clean** |
56
- | **Setup Overhead** | Complex SDK configurations | **Single REST API / Docker Container** |
57
-
58
- ---
59
-
60
- ## ✨ Key Features
61
-
62
- * **AI Chat:** Multi-turn conversational memory with Server-Sent Events (SSE) streaming support (OpenAI-compatible `data: [DONE]` format).
63
- * **Imagen 3 Image Gen:** Generate stunning visuals from text prompts, perform image-to-image editing (e.g., altering clothing, backgrounds, or assets), or upload up to 10 images simultaneously for multi-image analysis.
64
- * **Gemini Video Gen:** Generate text-to-video clips, image-to-video reference animations, or perform complex video-to-video visual edits (e.g., turning a beach video loop into a Studio Ghibli hand-drawn anime style).
65
- * **Music Generation:** Produce vocal and instrumental tracks on-demand, returned as local static URL references.
66
- * **Automated Session Hot-Reload:** Hot-reloads session settings and tokens on cookie sync updates, allowing uninterrupted server operation.
67
-
68
- ---
69
-
70
- ## 🏁 Quick Start
71
-
72
- ### Step 1: Install Chrome Cookie Bridge Extension
73
- 1. Open Google Chrome and go to `chrome://extensions/`.
74
- 2. Enable **Developer mode** (top-right toggle).
75
- 3. Click **Load unpacked** (top-left) and select the `extension` folder located in this repository.
76
- 4. Log into [gemini.google.com](https://gemini.google.com) on this browser instance.
77
- 5. The extension will automatically detect your active session and sync your cookies to the Go backend WebSocket server (default port `9222`).
78
-
79
- ---
80
-
81
- ### Step 2: Run the Server
82
-
83
- Choose your preferred deployment method below:
84
-
85
- #### Option A: Pre-built Binary (Recommended & Easiest)
86
- 1. Download the latest release binary matching your operating system from the GitHub Releases.
87
- 2. Make the binary executable and launch it:
88
- * **macOS / Linux:**
89
- ```bash
90
- chmod +x free-gemini-api-mac-arm64
91
- ./free-gemini-api-mac-arm64
92
- ```
93
- * **Windows:** Double-click on `free-gemini-api-win-x64.exe` or run it from CMD/PowerShell.
94
-
95
- #### Option B: From Source (For Local Dev)
96
- Ensure you have Go 1.21+ installed on your system. Watermark removal and all endpoints run natively without any Python requirements!
97
- ```bash
98
- # Run the Go server
99
- go run .
100
- ```
101
-
102
- #### Option C: Docker Setup
103
- Run the pre-built Docker container:
104
- ```bash
105
- docker run -d --name free-gemini-api \
106
- -e WS_PORT=9222 \
107
- -e PORT=8000 \
108
- -p 8000:8000 \
109
- -p 9222:9222 \
110
- akashyadav758/free-gemini-api:latest
111
- ```
112
- -e WS_PORT=9222 \
113
- -e PORT=8000 \
114
- -p 8000:8000 \
115
- -p 9222:9222 \
116
- akashyadav758/free-gemini-api:latest
117
- ```
118
-
119
- ---
120
-
121
- ### Step 3: Environment Variables (`.env`)
122
- Create a `.env` file in the root of the project to customize connection configurations:
123
- ```env
124
- WS_PORT=8001 # WebSocket cookie bridge port (configured in extension)
125
- PORT=8000 # Port on which this Go API server runs
126
- ```
127
-
128
- ---
129
-
130
- ## 📡 API Endpoints
131
-
132
- ### 1. `POST /chat` — Unified Interface
133
- Handles text conversations, streaming, image generation, multi-image analysis, and video processing.
134
-
135
- #### parameters
136
-
137
- | Field | Type | Description |
138
- |:---|:---|:---|
139
- | `prompt` | `string` | **Required.** The instruction or text query. |
140
- | `user_id` | `string` | Optional. Isolated session identity. |
141
- | `new_chat` | `bool` | Optional. Clear conversational history context. |
142
- | `stream` | `bool` | Optional. Stream responses back via SSE. |
143
- | `image` | `file(s)` | Optional. Multi-part form image upload (supports up to 10 files). |
144
-
145
- ---
146
-
147
- ### End-Point Integrations & Examples
148
-
149
- #### A. Text Generation (Standard JSON)
150
- ```bash
151
- curl -X POST http://localhost:8000/chat \
152
- -H "Content-Type: application/json" \
153
- -d '{
154
- "prompt": "Explain quantum computing in three clear bullet points.",
155
- "user_id": "test_user_1",
156
- "new_chat": true
157
- }'
158
- ```
159
-
160
- #### B. Streaming Text Chat (Server-Sent Events)
161
- ```bash
162
- curl -N -X POST http://localhost:8000/chat \
163
- -H "Content-Type: application/json" \
164
- -d '{
165
- "prompt": "Write a short creative story about a developer and an AI assistant.",
166
- "user_id": "test_user_1",
167
- "stream": true
168
- }'
169
- ```
170
-
171
- #### C. Imagen 3 Image Generation (Text → Image)
172
- Prompt the system to generate pictures, which are automatically downloaded, cleaned of watermarks, and saved locally:
173
- ```bash
174
- curl -X POST http://localhost:8000/chat \
175
- -H "Content-Type: application/json" \
176
- -d '{
177
- "prompt": "Generate a beautiful landscape image of a sunset over snow-covered mountains, highly detailed.",
178
- "user_id": "test_user_1",
179
- "new_chat": true
180
- }'
181
- ```
182
-
183
- #### D. Image Editing & Variations (Image + Text Prompt)
184
- Upload an existing image and tell the AI to edit it in place:
185
- ```bash
186
- curl -X POST http://localhost:8000/chat \
187
- -F "prompt=Change the background of this image to a busy neon cyberpunk street" \
188
- -F "image=@/path/to/my_photo.png" \
189
- -F "user_id=test_user_1" \
190
- -F "new_chat=true"
191
- ```
192
-
193
- #### E. Gemini Video Generation (Image → Video / Text → Video)
194
- Provide an image reference and animate it, or generate fresh video segments from text:
195
- ```bash
196
- curl -X POST http://localhost:8000/chat \
197
- -F "prompt=Animate this scene: make the ocean waves crash dynamically on the shore with smooth cinematic motions" \
198
- -F "image=@/path/to/beach_scene.png" \
199
- -F "user_id=test_user_1" \
200
- -F "new_chat=true"
201
- ```
202
-
203
- #### F. Video-to-Video Visual Styling (Video File Input)
204
- Upload a video and completely rewrite its artistic style:
205
- ```bash
206
- curl -X POST http://localhost:8000/chat \
207
- -F "prompt=Edit this video: Convert the entire visual style of this video into a beautiful Studio Ghibli hand-drawn anime style." \
208
- -F "image=@/path/to/original_video.mp4;type=video/mp4" \
209
- -F "user_id=test_user_1" \
210
- -F "new_chat=true"
211
- ```
212
-
213
- ---
214
-
215
- ### 2. `POST /music` — Song & Audio Track Generation
216
- Generates audio tracks from description prompts.
217
- ```bash
218
- curl -X POST http://localhost:8000/music \
219
- -H "Content-Type: application/json" \
220
- -d '{
221
- "prompt": "A relaxing lofi chillhop beat with smooth piano and rain sounds",
222
- "user_id": "test_user_1",
223
- "new_chat": true
224
- }'
225
- ```
226
-
227
- ---
228
-
229
- ### Response Structure (JSON Example)
230
- ```json
231
- {
232
- "text": "I have successfully generated your media loop based on the prompt...",
233
- "conversation_id": "c_3eeb67f56f0c82f2",
234
- "response_id": "r_5fd71304b0a2190b",
235
- "choice_id": "rc_82705406bcc3a2f7",
236
- "images": [
237
- "http://localhost:8000/static/img_r_5fd71304b0a2190b_0.png"
238
- ],
239
- "videos": [
240
- "http://localhost:8000/static/vid_r_5fd71304b0a2190b_0.mp4"
241
- ],
242
- "music": [],
243
- "elapsed": 43.56
244
- }
245
- ```
246
- *(All generated files served dynamically from `/static/*` have already undergone in-place watermark removal).*
247
-
248
- ---
249
-
250
- ## 🐍 SDK Integration
251
-
252
- ### Python Example
253
- A production-ready script utilizing Python's `requests` library to interface with the REST server:
254
-
255
- ```python
256
- import requests
257
- import json
258
-
259
- BASE_URL = "http://localhost:8000"
260
-
261
- def generate_text(prompt: str, user_id: str = "py_user"):
262
- url = f"{BASE_URL}/chat"
263
- payload = {
264
- "prompt": prompt,
265
- "user_id": user_id,
266
- "new_chat": True
267
- }
268
- headers = {"Content-Type": "application/json"}
269
-
270
- response = requests.post(url, json=payload, headers=headers)
271
- return response.json()
272
-
273
- def edit_image_to_video(prompt: str, image_path: str, user_id: str = "py_user"):
274
- url = f"{BASE_URL}/chat"
275
- files = {
276
- "image": (image_path, open(image_path, "rb"), "image/png")
277
- }
278
- data = {
279
- "prompt": prompt,
280
- "user_id": user_id,
281
- "new_chat": "true"
282
- }
283
-
284
- response = requests.post(url, files=files, data=data)
285
- return response.json()
286
-
287
- if __name__ == "__main__":
288
- # Generate simple text
289
- print("Sending text prompt...")
290
- text_res = generate_text("Explain machine learning in one sentence.")
291
- print("Response:", text_res["text"])
292
-
293
- # Generate / Edit Image-to-Video
294
- # print(edit_image_to_video("Animate a flying eagle in the clouds", "eagle.png"))
295
- ```
296
-
297
- ### Node.js Example (Streaming Support)
298
- An asynchronous ES6 script displaying streaming chunks using standard node-fetch:
299
-
300
- ```javascript
301
- const BASE_URL = "http://localhost:8000";
302
-
303
- async function streamStory(prompt) {
304
- const response = await fetch(`${BASE_URL}/chat`, {
305
- method: "POST",
306
- headers: { "Content-Type": "application/json" },
307
- body: JSON.stringify({
308
- prompt: prompt,
309
- stream: true,
310
- user_id: "node_user",
311
- new_chat: true
312
- })
313
- });
314
-
315
- const reader = response.body.getReader();
316
- const decoder = new TextDecoder("utf-8");
317
-
318
- while (true) {
319
- const { done, value } = await reader.read();
320
- if (done) break;
321
-
322
- const chunk = decoder.decode(value);
323
- // Print SSE stream lines
324
- console.log(chunk);
325
- }
326
- }
327
-
328
- streamStory("Write a short futuristic sci-fi paragraph.");
329
- ```
330
-
331
- ---
332
-
333
- ## 🏗️ Architecture
334
-
335
- ```
336
- ┌────────────────────────┐
337
- │ REST Client │
338
- │ (Python, Node, cURL) │
339
- └───────────┬────────────┘
340
- │
341
- │ HTTP REST / SSE (Port 8000)
342
- ▼
343
- ┌─────────────────────────────────────────────────────────────────────────────────────────┐
344
- │ Go API Gateway (Fiber v3 Server) │
345
- │ │
346
- │ ┌────────────────┐ ┌──────────────────┐ ┌────────────────┐ ┌────────────┐ │
347
- │ │ Unified Chat │ │ Streaming Engine │ │ Media Down- │ │ In-Place │ │
348
- │ │ Endpoints │ │ (Server-Sent │ │ loader & Cookie│ │ Watermark │ │
349
- │ │ (POST /chat) │ │ Events) │ │ Injector │ │ Processor │ │
350
- │ └───────┬────────┘ └────────┬─────────┘ └────────┬───────┘ └──────┬─────┘ │
351
- └──────────┼───────────────────────┼────────────────────────┼────────────────────┼────────┘
352
- │ │ │ │
353
- │ JSON RPC payload │ Chunk Streams │ Follows manual │ Executes
354
- │ │ │ redirects │ watermark.go
355
- ▼ ▼ ▼ ▼
356
- ┌─────────────────────────────────────────────────────────────────────────────────────────┐
357
- │ Google Gemini Web API Backend │
358
- │ (consumer.rpc.StreamGenerate / hNvQHb video poller / Imagen 3 Engine) │
359
- └─────────────────────────────────────────────────────────▲───────────────────────────────┘
360
- │
361
- │ Live Cookie Synchronization
362
- │ (WebSocket Bridge Port 9222)
363
- ┌────────┴────────┐
364
- │ Chrome Extension│
365
- │ Cookie Bridge │
366
- └─────────────────┘
367
- ```
368
-
369
- ### Directory Structure
370
- ```
371
- ├── main.go # Fiber HTTP engine startup, Universal REST routers
372
- ├── .env # Port and WebSocket bridge configs
373
- ├── cookies.json # Live cookie storage, written dynamically via extension
374
- ├── gemini/
375
- │ ├── client.go # Session initialization, API calls, redirect tracking
376
- │ ├── models.go # API schemas and structures
377
- │ ├── monitor.go # WebSocket bridge and cookies listener
378
- │ └── watermark.go # Native Go reverse alpha-blending watermark remover
379
- └── extension/
380
- ├── manifest.json # Chrome browser extension manifest definitions
381
- ├── background.js # WebSocket connection to Go backend, cookie event handlers
382
- ├── popup.html # Interactive developer status panel UI
383
- └── popup.js # Local settings controller
384
- ```
385
-
386
- ---
387
-
388
- ## ⚠️ Limits & Notes
389
-
390
- * **Video Quota limits:** Gemini Video generation is limited to standard consumer daily accounts (~3-5 videos daily). The system returns an immediate refusal object with `videos: null` once limits are triggered.
391
- * **WebSocket Cookie Sync:** Ensure you load the extension located under `/extension` in your browser to automatically stream and sync active cookies to the backend Go server on port `9222`.
392
-
393
- ---
394
-
395
- <div align="center">
396
-
397
- **⭐ Star this repository if this project helps you! ⭐**
398
-
399
- *Disclaimer: This is an unofficial proxy wrapper built for educational and personal research projects. Adhere to Google Terms of Service.*
400
-
401
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
monitor/main.go CHANGED
@@ -546,6 +546,11 @@ func authOK(w http.ResponseWriter, r *http.Request) bool {
546
  if got == "" {
547
  got = r.URL.Query().Get("key")
548
  }
 
 
 
 
 
549
  if got != apiKey {
550
  http.Error(w, "unauthorized", http.StatusUnauthorized)
551
  return false
@@ -553,6 +558,18 @@ func authOK(w http.ResponseWriter, r *http.Request) bool {
553
  return true
554
  }
555
 
 
 
 
 
 
 
 
 
 
 
 
 
556
  // gatewayHandler builds an API-key-gated reverse proxy that strips prefix and
557
  // forwards to target (e.g. /gpt/api/chat -> http://127.0.0.1:9225/api/chat).
558
  func gatewayHandler(prefix, target string) http.HandlerFunc {
@@ -606,20 +623,28 @@ func main() {
606
  http.NotFound(w, r)
607
  return
608
  }
 
 
 
 
 
 
 
 
609
  w.Header().Set("Content-Type", "text/html; charset=utf-8")
610
  w.Write(indexHTML)
611
  })
612
- http.HandleFunc("/api/tabs", tabsHandler)
613
- http.HandleFunc("/api/screen", screenHandler)
614
- http.HandleFunc("/api/input", inputHandler)
615
- http.HandleFunc("/api/navigate", navigateHandler)
616
- http.HandleFunc("/api/reload", reloadHandler)
617
- http.HandleFunc("/api/back", historyHandler(-1))
618
- http.HandleFunc("/api/forward", historyHandler(+1))
619
- http.HandleFunc("/api/newtab", newtabHandler)
620
- http.HandleFunc("/api/closetab", closetabHandler)
621
- http.HandleFunc("/api/stats", statsHandler)
622
- http.HandleFunc("/chrome.log", chromeLogHandler)
623
  http.HandleFunc("/logs/", backendLogHandler)
624
 
625
  // API gateway → the three backend servers on localhost (API-key gated).
 
546
  if got == "" {
547
  got = r.URL.Query().Get("key")
548
  }
549
+ if got == "" {
550
+ if c, err := r.Cookie("apikey"); err == nil {
551
+ got = c.Value
552
+ }
553
+ }
554
  if got != apiKey {
555
  http.Error(w, "unauthorized", http.StatusUnauthorized)
556
  return false
 
558
  return true
559
  }
560
 
561
+ // gate wraps a handler so it requires the API key (Bearer header, ?key=, or the
562
+ // apikey cookie). Every monitor route that can view or drive the logged-in
563
+ // browser is gated — nothing is publicly reachable.
564
+ func gate(h http.HandlerFunc) http.HandlerFunc {
565
+ return func(w http.ResponseWriter, r *http.Request) {
566
+ if !authOK(w, r) {
567
+ return
568
+ }
569
+ h(w, r)
570
+ }
571
+ }
572
+
573
  // gatewayHandler builds an API-key-gated reverse proxy that strips prefix and
574
  // forwards to target (e.g. /gpt/api/chat -> http://127.0.0.1:9225/api/chat).
575
  func gatewayHandler(prefix, target string) http.HandlerFunc {
 
623
  http.NotFound(w, r)
624
  return
625
  }
626
+ if !authOK(w, r) {
627
+ return
628
+ }
629
+ // If the key arrived via ?key=, persist it as a cookie so the in-page
630
+ // /api/* fetches (same origin) stay authorized without re-passing it.
631
+ if k := r.URL.Query().Get("key"); k != "" && k == apiKey {
632
+ http.SetCookie(w, &http.Cookie{Name: "apikey", Value: k, Path: "/", HttpOnly: true, SameSite: http.SameSiteStrictMode})
633
+ }
634
  w.Header().Set("Content-Type", "text/html; charset=utf-8")
635
  w.Write(indexHTML)
636
  })
637
+ http.HandleFunc("/api/tabs", gate(tabsHandler))
638
+ http.HandleFunc("/api/screen", gate(screenHandler))
639
+ http.HandleFunc("/api/input", gate(inputHandler))
640
+ http.HandleFunc("/api/navigate", gate(navigateHandler))
641
+ http.HandleFunc("/api/reload", gate(reloadHandler))
642
+ http.HandleFunc("/api/back", gate(historyHandler(-1)))
643
+ http.HandleFunc("/api/forward", gate(historyHandler(+1)))
644
+ http.HandleFunc("/api/newtab", gate(newtabHandler))
645
+ http.HandleFunc("/api/closetab", gate(closetabHandler))
646
+ http.HandleFunc("/api/stats", gate(statsHandler))
647
+ http.HandleFunc("/chrome.log", gate(chromeLogHandler))
648
  http.HandleFunc("/logs/", backendLogHandler)
649
 
650
  // API gateway → the three backend servers on localhost (API-key gated).