Spaces:
Runtime error
Runtime error
akashyadav758 Claude Opus 4.8 (1M context) commited on
Commit Β·
23a7459
1
Parent(s): 6d42e1f
Remove Flow agent from stack (extension, server, gateway, monitor tab)
Browse filesCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Dockerfile +3 -11
- README.md +1 -2
- docker-compose.yml +6 -7
- monitor/main.go +8 -11
- start_hf.sh +10 -11
Dockerfile
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
# Build the navigator monitor server (GPT / Gemini
|
| 2 |
FROM golang:1.22-bookworm AS monitor-build
|
| 3 |
WORKDIR /src
|
| 4 |
COPY monitor/ ./
|
|
@@ -29,7 +29,6 @@ USER root
|
|
| 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 |
|
| 34 |
# 3-tab monitor binary (replaces the single-view base monitor)
|
| 35 |
COPY --from=monitor-build /monitor /opt/monitor3/monitor
|
|
@@ -41,12 +40,6 @@ COPY --from=profilesync-build /profilesync /opt/profilesync/profilesync
|
|
| 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 |
-
|
| 46 |
-
# Flow server is Python (FastAPI/uvicorn). Base image has python3; add pip + deps.
|
| 47 |
-
RUN apt-get update && apt-get install -y --no-install-recommends python3-pip && \
|
| 48 |
-
pip3 install --no-cache-dir --break-system-packages -r /opt/flow-srv/requirements.txt && \
|
| 49 |
-
apt-get clean && rm -rf /var/lib/apt/lists/*
|
| 50 |
|
| 51 |
# Install Chrome for Testing (unbranded). Branded google-chrome-stable (>=128)
|
| 52 |
# silently ignores --load-extension, so unpacked extensions never load. CfT is the
|
|
@@ -60,9 +53,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends unzip && \
|
|
| 60 |
apt-get clean && rm -rf /var/lib/apt/lists/*
|
| 61 |
|
| 62 |
# Set correct permissions and ownership
|
| 63 |
-
RUN
|
| 64 |
-
|
| 65 |
-
chmod -R 755 /opt/gpt-extension /opt/gemini-extension /opt/flow-extension /opt/chrome-linux64 /opt/monitor3 /opt/profilesync /opt/chatgpt /opt/gemini-srv /opt/flow-srv
|
| 66 |
|
| 67 |
# Replace the start script with the non-root version
|
| 68 |
COPY --chmod=755 start_hf.sh /start.sh
|
|
|
|
| 1 |
+
# Build the navigator monitor server (GPT / Gemini live view) from source.
|
| 2 |
FROM golang:1.22-bookworm AS monitor-build
|
| 3 |
WORKDIR /src
|
| 4 |
COPY monitor/ ./
|
|
|
|
| 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 |
|
| 33 |
# 3-tab monitor binary (replaces the single-view base monitor)
|
| 34 |
COPY --from=monitor-build /monitor /opt/monitor3/monitor
|
|
|
|
| 40 |
COPY --from=chatgpt-build /agent /opt/chatgpt/agent
|
| 41 |
COPY free-Chatgpt-api/config.json /opt/chatgpt/config.json
|
| 42 |
COPY --from=gemini-build /free-gemini-api /opt/gemini-srv/free-gemini-api
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
# Install Chrome for Testing (unbranded). Branded google-chrome-stable (>=128)
|
| 45 |
# silently ignores --load-extension, so unpacked extensions never load. CfT is the
|
|
|
|
| 53 |
apt-get clean && rm -rf /var/lib/apt/lists/*
|
| 54 |
|
| 55 |
# Set correct permissions and ownership
|
| 56 |
+
RUN chown -R 1000:1000 /opt/gpt-extension /opt/gemini-extension /opt/chrome-linux64 /opt/monitor3 /opt/profilesync /opt/chatgpt /opt/gemini-srv && \
|
| 57 |
+
chmod -R 755 /opt/gpt-extension /opt/gemini-extension /opt/chrome-linux64 /opt/monitor3 /opt/profilesync /opt/chatgpt /opt/gemini-srv
|
|
|
|
| 58 |
|
| 59 |
# Replace the start script with the non-root version
|
| 60 |
COPY --chmod=755 start_hf.sh /start.sh
|
README.md
CHANGED
|
@@ -27,9 +27,8 @@ automate workflows for ChatGPT, Google Gemini, and Google Flow.
|
|
| 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 |
-
|
| 33 |
also contains the matching backend server.
|
| 34 |
|
| 35 |
---
|
|
|
|
| 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 |
|
| 31 |
+
Both are Manifest V3 extensions with background service workers. Each subfolder
|
| 32 |
also contains the matching backend server.
|
| 33 |
|
| 34 |
---
|
docker-compose.yml
CHANGED
|
@@ -1,17 +1,16 @@
|
|
| 1 |
-
# Runs the whole stack in one container: headless Chrome +
|
| 2 |
-
# (which also serves the API gateway) + the
|
| 3 |
#
|
| 4 |
-
# The chrome image (built from ./Dockerfile) now bakes in
|
| 5 |
# launches them on localhost alongside Chrome β exactly what the extensions expect (they dial
|
| 6 |
-
# 127.0.0.1:9225/9226
|
| 7 |
# collide on the same ports. Only port 3001 is published.
|
| 8 |
#
|
| 9 |
# Internal port map (all on the container's 127.0.0.1):
|
| 10 |
# chrome : 9222 CDP, 9223 CDP-proxy
|
| 11 |
-
# monitor : 3001 UI + API gateway (/gpt /gemini
|
| 12 |
# chatgpt : 9225 (ws + http API)
|
| 13 |
# gemini : 8000 http API, 9226 cookie-WS
|
| 14 |
-
# flow : 8101 http API, 8100 ext-callback, 9227 cookie-WS
|
| 15 |
|
| 16 |
services:
|
| 17 |
chrome:
|
|
@@ -20,7 +19,7 @@ services:
|
|
| 20 |
ports:
|
| 21 |
- "3001:3001" # monitor UI + API gateway (the only published port)
|
| 22 |
environment:
|
| 23 |
-
API_KEY: ${API_KEY:-} # gates /gpt /gemini
|
| 24 |
volumes:
|
| 25 |
- chrome-profile:/home/chrome/data # persists cookies/logins across restarts
|
| 26 |
restart: unless-stopped
|
|
|
|
| 1 |
+
# Runs the whole stack in one container: headless Chrome + 2 extensions + the monitor
|
| 2 |
+
# (which also serves the API gateway) + the two backend servers.
|
| 3 |
#
|
| 4 |
+
# The chrome image (built from ./Dockerfile) now bakes in both servers and start_hf.sh
|
| 5 |
# launches them on localhost alongside Chrome β exactly what the extensions expect (they dial
|
| 6 |
+
# 127.0.0.1:9225/9226). So there are no separate server containers anymore; that would
|
| 7 |
# collide on the same ports. Only port 3001 is published.
|
| 8 |
#
|
| 9 |
# Internal port map (all on the container's 127.0.0.1):
|
| 10 |
# chrome : 9222 CDP, 9223 CDP-proxy
|
| 11 |
+
# monitor : 3001 UI + API gateway (/gpt /gemini)
|
| 12 |
# chatgpt : 9225 (ws + http API)
|
| 13 |
# gemini : 8000 http API, 9226 cookie-WS
|
|
|
|
| 14 |
|
| 15 |
services:
|
| 16 |
chrome:
|
|
|
|
| 19 |
ports:
|
| 20 |
- "3001:3001" # monitor UI + API gateway (the only published port)
|
| 21 |
environment:
|
| 22 |
+
API_KEY: ${API_KEY:-} # gates /gpt /gemini; from .env. Unset = APIs disabled (503)
|
| 23 |
volumes:
|
| 24 |
- chrome-profile:/home/chrome/data # persists cookies/logins across restarts
|
| 25 |
restart: unless-stopped
|
monitor/main.go
CHANGED
|
@@ -44,7 +44,6 @@ type knownTab struct {
|
|
| 44 |
var knownTabs = []knownTab{
|
| 45 |
{"ChatGPT", "https://chatgpt.com/", "chatgpt.com"},
|
| 46 |
{"Gemini", "https://gemini.google.com/", "gemini.google.com"},
|
| 47 |
-
{"Flow", "https://labs.google/fx", "labs.google"},
|
| 48 |
}
|
| 49 |
|
| 50 |
// cdpTarget mirrors the relevant fields of an entry from GET /json.
|
|
@@ -487,8 +486,8 @@ func chromeLogHandler(w http.ResponseWriter, r *http.Request) {
|
|
| 487 |
}
|
| 488 |
|
| 489 |
// backendLogHandler serves the per-server logs (API-key gated) so we can diagnose
|
| 490 |
-
// the gpt/gemini
|
| 491 |
-
// /logs/chatgpt /logs/gemini
|
| 492 |
func backendLogHandler(w http.ResponseWriter, r *http.Request) {
|
| 493 |
if !authOK(w, r) {
|
| 494 |
return
|
|
@@ -497,12 +496,11 @@ func backendLogHandler(w http.ResponseWriter, r *http.Request) {
|
|
| 497 |
paths := map[string]string{
|
| 498 |
"chatgpt": "/home/chrome/chatgpt.log",
|
| 499 |
"gemini": "/home/chrome/gemini.log",
|
| 500 |
-
"flow": "/home/chrome/flow.log",
|
| 501 |
"monitor": "/home/chrome/monitor.log",
|
| 502 |
}
|
| 503 |
p, ok := paths[name]
|
| 504 |
if !ok {
|
| 505 |
-
http.Error(w, "unknown log (use chatgpt|gemini|
|
| 506 |
return
|
| 507 |
}
|
| 508 |
f, err := os.Open(p)
|
|
@@ -528,10 +526,10 @@ func statsHandler(w http.ResponseWriter, r *http.Request) {
|
|
| 528 |
}
|
| 529 |
|
| 530 |
// ---- API gateway ----------------------------------------------------------
|
| 531 |
-
// The monitor doubles as the single public entry point for the
|
| 532 |
// servers that run on localhost inside this same container. HF exposes only one
|
| 533 |
-
// port (3001), so /gpt
|
| 534 |
-
// loopback HTTP ports.
|
| 535 |
|
| 536 |
var apiKey = os.Getenv("API_KEY")
|
| 537 |
|
|
@@ -626,7 +624,7 @@ func main() {
|
|
| 626 |
// HuggingFace's own auth already gates who can reach it (the owner). The browser
|
| 627 |
// can't attach ?key= when HF serves the private subdomain, so requiring our key
|
| 628 |
// here locks the owner out of their own live view. Only the AI gateway
|
| 629 |
-
// (/gpt /gemini
|
| 630 |
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
| 631 |
if r.URL.Path != "/" {
|
| 632 |
http.NotFound(w, r)
|
|
@@ -651,9 +649,8 @@ func main() {
|
|
| 651 |
// API gateway β the three backend servers on localhost (API-key gated).
|
| 652 |
http.HandleFunc("/gpt/", gatewayHandler("/gpt", "http://127.0.0.1:9225"))
|
| 653 |
http.HandleFunc("/gemini/", gatewayHandler("/gemini", "http://127.0.0.1:8000"))
|
| 654 |
-
http.HandleFunc("/flow/", gatewayHandler("/flow", "http://127.0.0.1:8101"))
|
| 655 |
if apiKey == "" {
|
| 656 |
-
log.Println("WARNING: API_KEY not set β /gpt /gemini
|
| 657 |
}
|
| 658 |
|
| 659 |
addr := ":3001"
|
|
|
|
| 44 |
var knownTabs = []knownTab{
|
| 45 |
{"ChatGPT", "https://chatgpt.com/", "chatgpt.com"},
|
| 46 |
{"Gemini", "https://gemini.google.com/", "gemini.google.com"},
|
|
|
|
| 47 |
}
|
| 48 |
|
| 49 |
// cdpTarget mirrors the relevant fields of an entry from GET /json.
|
|
|
|
| 486 |
}
|
| 487 |
|
| 488 |
// backendLogHandler serves the per-server logs (API-key gated) so we can diagnose
|
| 489 |
+
// the gpt/gemini backends without shelling into the container:
|
| 490 |
+
// /logs/chatgpt /logs/gemini (also /logs/monitor)
|
| 491 |
func backendLogHandler(w http.ResponseWriter, r *http.Request) {
|
| 492 |
if !authOK(w, r) {
|
| 493 |
return
|
|
|
|
| 496 |
paths := map[string]string{
|
| 497 |
"chatgpt": "/home/chrome/chatgpt.log",
|
| 498 |
"gemini": "/home/chrome/gemini.log",
|
|
|
|
| 499 |
"monitor": "/home/chrome/monitor.log",
|
| 500 |
}
|
| 501 |
p, ok := paths[name]
|
| 502 |
if !ok {
|
| 503 |
+
http.Error(w, "unknown log (use chatgpt|gemini|monitor)", http.StatusNotFound)
|
| 504 |
return
|
| 505 |
}
|
| 506 |
f, err := os.Open(p)
|
|
|
|
| 526 |
}
|
| 527 |
|
| 528 |
// ---- API gateway ----------------------------------------------------------
|
| 529 |
+
// The monitor doubles as the single public entry point for the backend
|
| 530 |
// servers that run on localhost inside this same container. HF exposes only one
|
| 531 |
+
// port (3001), so /gpt and /gemini are reverse-proxied to the servers'
|
| 532 |
+
// loopback HTTP ports. Both are gated by an API key (fail-closed).
|
| 533 |
|
| 534 |
var apiKey = os.Getenv("API_KEY")
|
| 535 |
|
|
|
|
| 624 |
// HuggingFace's own auth already gates who can reach it (the owner). The browser
|
| 625 |
// can't attach ?key= when HF serves the private subdomain, so requiring our key
|
| 626 |
// here locks the owner out of their own live view. Only the AI gateway
|
| 627 |
+
// (/gpt /gemini) and /logs stay API-key-gated for external programmatic use.
|
| 628 |
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
| 629 |
if r.URL.Path != "/" {
|
| 630 |
http.NotFound(w, r)
|
|
|
|
| 649 |
// API gateway β the three backend servers on localhost (API-key gated).
|
| 650 |
http.HandleFunc("/gpt/", gatewayHandler("/gpt", "http://127.0.0.1:9225"))
|
| 651 |
http.HandleFunc("/gemini/", gatewayHandler("/gemini", "http://127.0.0.1:8000"))
|
|
|
|
| 652 |
if apiKey == "" {
|
| 653 |
+
log.Println("WARNING: API_KEY not set β /gpt /gemini are disabled (503) until it is set")
|
| 654 |
}
|
| 655 |
|
| 656 |
addr := ":3001"
|
start_hf.sh
CHANGED
|
@@ -106,13 +106,12 @@ touch /home/chrome/chrome.log
|
|
| 106 |
echo "π Starting CDP Proxy..."
|
| 107 |
socat TCP-LISTEN:9223,fork,bind=0.0.0.0 TCP:127.0.0.1:9222 &
|
| 108 |
|
| 109 |
-
# 6a. Start the
|
| 110 |
-
# gateway and fronts them on :3001 (/gpt, /gemini
|
| 111 |
# and runs in the background so a crash never blocks the boot.
|
| 112 |
-
echo "π§© Starting backend API servers (gpt / gemini
|
| 113 |
( cd /opt/chatgpt && ./agent >> /home/chrome/chatgpt.log 2>&1 & )
|
| 114 |
( cd /opt/gemini-srv && WS_PORT=9226 PORT=8000 ./free-gemini-api >> /home/chrome/gemini.log 2>&1 & )
|
| 115 |
-
( cd /opt/flow-srv && WS_PORT=9227 HTTP_PORT=8100 python3 -m uvicorn cli.api:app --host 127.0.0.1 --port 8101 >> /home/chrome/flow.log 2>&1 & )
|
| 116 |
|
| 117 |
# 6b. Periodic profile backup (safety net if HF kills the container without a clean
|
| 118 |
# SIGTERM). Best-effort every 5 minutes; the shutdown trap does the final one.
|
|
@@ -124,17 +123,17 @@ fi
|
|
| 124 |
# 6c. Provide a valid per-user runtime dir. Chrome's mojo/IPC layer and each MV3
|
| 125 |
# extension service worker need this; without it Chrome logs
|
| 126 |
# "XDG_RUNTIME_DIR is invalid or not set" and the extension service workers
|
| 127 |
-
# intermittently fail to spawn (DidStartWorkerFail) β the gpt/gemini
|
| 128 |
# extensions never connect. Purely additive: just creates a dir and exports it.
|
| 129 |
export XDG_RUNTIME_DIR=/tmp/runtime-chrome
|
| 130 |
mkdir -p "$XDG_RUNTIME_DIR" && chmod 700 "$XDG_RUNTIME_DIR"
|
| 131 |
|
| 132 |
# 7. Launch Chrome Headless
|
| 133 |
# NOTE: do NOT add --renderer-process-limit=1 / --process-per-site / --no-zygote here.
|
| 134 |
-
# Each
|
| 135 |
-
#
|
| 136 |
# starves those workers β they fail to start (DidStartWorkerFail) so the extension never
|
| 137 |
-
# connects, and when one does start, executeScript hangs β the /gpt /gemini
|
| 138 |
# hang forever. HF cpu-basic has 16 GB (we use ~1β2 GB), so the memory "savings" weren't
|
| 139 |
# needed and broke the extensions. Keep Chrome multi-process.
|
| 140 |
echo "β¨ Launching Chrome Headless..."
|
|
@@ -173,8 +172,8 @@ echo "β¨ Launching Chrome Headless..."
|
|
| 173 |
--disable-background-timer-throttling \
|
| 174 |
--disable-renderer-backgrounding \
|
| 175 |
--disable-backgrounding-occluded-windows \
|
| 176 |
-
--load-extension=/opt/gpt-extension,/opt/gemini-extension
|
| 177 |
-
--disable-extensions-except=/opt/gpt-extension,/opt/gemini-extension
|
| 178 |
--disable-translate \
|
| 179 |
--memory-pressure-off \
|
| 180 |
--disable-client-side-phishing-detection \
|
|
@@ -193,4 +192,4 @@ echo "β¨ Launching Chrome Headless..."
|
|
| 193 |
--disable-site-isolation-trials \
|
| 194 |
--js-flags="--max-old-space-size=512" \
|
| 195 |
--metrics-recording-only \
|
| 196 |
-
'
|
|
|
|
| 106 |
echo "π Starting CDP Proxy..."
|
| 107 |
socat TCP-LISTEN:9223,fork,bind=0.0.0.0 TCP:127.0.0.1:9222 &
|
| 108 |
|
| 109 |
+
# 6a. Start the backend API servers on localhost. The monitor doubles as a
|
| 110 |
+
# gateway and fronts them on :3001 (/gpt, /gemini). Each logs separately
|
| 111 |
# and runs in the background so a crash never blocks the boot.
|
| 112 |
+
echo "π§© Starting backend API servers (gpt / gemini)..."
|
| 113 |
( cd /opt/chatgpt && ./agent >> /home/chrome/chatgpt.log 2>&1 & )
|
| 114 |
( cd /opt/gemini-srv && WS_PORT=9226 PORT=8000 ./free-gemini-api >> /home/chrome/gemini.log 2>&1 & )
|
|
|
|
| 115 |
|
| 116 |
# 6b. Periodic profile backup (safety net if HF kills the container without a clean
|
| 117 |
# SIGTERM). Best-effort every 5 minutes; the shutdown trap does the final one.
|
|
|
|
| 123 |
# 6c. Provide a valid per-user runtime dir. Chrome's mojo/IPC layer and each MV3
|
| 124 |
# extension service worker need this; without it Chrome logs
|
| 125 |
# "XDG_RUNTIME_DIR is invalid or not set" and the extension service workers
|
| 126 |
+
# intermittently fail to spawn (DidStartWorkerFail) β the gpt/gemini
|
| 127 |
# extensions never connect. Purely additive: just creates a dir and exports it.
|
| 128 |
export XDG_RUNTIME_DIR=/tmp/runtime-chrome
|
| 129 |
mkdir -p "$XDG_RUNTIME_DIR" && chmod 700 "$XDG_RUNTIME_DIR"
|
| 130 |
|
| 131 |
# 7. Launch Chrome Headless
|
| 132 |
# NOTE: do NOT add --renderer-process-limit=1 / --process-per-site / --no-zygote here.
|
| 133 |
+
# Each extension runs an MV3 service worker (its own renderer) and the chat
|
| 134 |
+
# pipeline injects via chrome.scripting.executeScript into the service tab. Capping renderers
|
| 135 |
# starves those workers β they fail to start (DidStartWorkerFail) so the extension never
|
| 136 |
+
# connects, and when one does start, executeScript hangs β the /gpt /gemini APIs
|
| 137 |
# hang forever. HF cpu-basic has 16 GB (we use ~1β2 GB), so the memory "savings" weren't
|
| 138 |
# needed and broke the extensions. Keep Chrome multi-process.
|
| 139 |
echo "β¨ Launching Chrome Headless..."
|
|
|
|
| 172 |
--disable-background-timer-throttling \
|
| 173 |
--disable-renderer-backgrounding \
|
| 174 |
--disable-backgrounding-occluded-windows \
|
| 175 |
+
--load-extension=/opt/gpt-extension,/opt/gemini-extension \
|
| 176 |
+
--disable-extensions-except=/opt/gpt-extension,/opt/gemini-extension \
|
| 177 |
--disable-translate \
|
| 178 |
--memory-pressure-off \
|
| 179 |
--disable-client-side-phishing-detection \
|
|
|
|
| 192 |
--disable-site-isolation-trials \
|
| 193 |
--js-flags="--max-old-space-size=512" \
|
| 194 |
--metrics-recording-only \
|
| 195 |
+
'https://chatgpt.com/' >> /home/chrome/chrome.log 2>&1
|