diff --git a/package.json b/package.json index b3c5ea5..0e33cbb 100644 --- a/package.json +++ b/package.json @@ -7,32 +7,13 @@ "server:dev": "pnpm run build && pnpm wrangler dev", "client": "pnpm client:dev", "client:build": "vite build", - "worker:build": "WRANGLER_LOG=info wrangler build", - "agents:dev": "(cd ../web-agent-rs; cargo run)", - "agents:docker": "(cd ../web-agent-rs; docker compose up --build)", - "dev:session-proxy": "wrangler dev -c workers/session-proxy/wrangler-session-proxy.toml", - "dev:image-generation-service": "wrangler dev -c workers/image-generation-service/wrangler-image-generation-service.toml", - "dev:email-service": "wrangler dev -c workers/email/wrangler-email.toml", - "dev:analytics-service": "wrangler dev -c workers/analytics/wrangler-analytics.toml", - "deploy:dev": "CI=true vite build && wrangler deploy --keep-vars=true --minify=true --env dev && pnpm deploy:session-proxy:dev", - "deploy:staging": "CI=true vite build && wrangler deploy --minify --env staging && pnpm deploy:session-proxy:staging", - "deploy:production": "CI=true vite build && wrangler deploy --minify --env production", - "deploy:production:full": "CI=true vite build && wrangler deploy --minify --env production && pnpm deploy:session-proxy:production && ./scripts/update_vpn_blocklist.sh && watch gh run list --workflow=update-vpn-blocklist.yaml", - "deploy:session-proxy:dev": "CI=true wrangler deploy --minify -c workers/session-proxy/wrangler-session-proxy.toml --env dev", - "deploy:session-proxy:staging": "CI=true wrangler deploy --minify -c workers/session-proxy/wrangler-session-proxy.toml --env staging", - "deploy:session-proxy:production": "CI=true wrangler deploy --minify -c workers/session-proxy/wrangler-session-proxy.toml --env production", - "deploy:rate-limiter": "CI=true wrangler deploy --minify -c workers/rate-limiter/wrangler-rate-limiter.toml", - "deploy:image-generation-service": "wrangler deploy -c workers/image-generation-service/wrangler-image-generation-service.toml", + "server:build": "WRANGLER_LOG=info wrangler build", + "deploy": "CI=true vite build && wrangler deploy --minify", "deploy:email-service": "wrangler deploy -c workers/email/wrangler-email.toml", "deploy:analytics-service": "wrangler deploy -c workers/analytics/wrangler-analytics.toml", - "deploy:next": "pnpm clean && pnpm install --frozen-lockfile && pnpm deploy:staging && pnpm deploy:production", - "deploy:all": "pnpm deploy:dev && pnpm deploy:staging && pnpm deploy:production", - "tail:dev": "wrangler tail", - "tail:staging": "wrangler tail --env staging", - "tail:production": "wrangler tail --env production", + "tail": "wrangler tail", "tail:email-service": "wrangler tail -c workers/email/wrangler-email.toml", "tail:analytics-service": "wrangler tail -c workers/analytics/wrangler-analytics.toml", - "tail:image-generation-service": "wrangler tail -c workers/image-generation-service/wrangler-image-generation-service.toml", "tail:session-proxy": "wrangler tail -c workers/session-proxy/wrangler-session-proxy.toml --env production" }, "dependencies": { diff --git a/workers/image-generation-service/main.js b/workers/image-generation-service/main.js deleted file mode 100644 index 5cc46bb..0000000 --- a/workers/image-generation-service/main.js +++ /dev/null @@ -1,114 +0,0 @@ -import { OpenAI } from "openai"; -import { WorkerEntrypoint } from "cloudflare:workers"; -import Replicate from "replicate"; - -export default class extends WorkerEntrypoint { - strategy; - - constructor(ctx, env) { - super(ctx, env); - switch (env.TEXT2IMAGE_PROVIDER) { - case "replicate": - this.strategy = new ReplicateStrategy(env); - break; - case "openai": - this.strategy = new OpenAiStrategy(env); - break; - default: - throw "Invalid or missing image provider"; - } - } - - async fetch(request) { - const { pathname, searchParams } = new URL(request.url); - - if (pathname === "/generate") { - const prompt = - searchParams.get("prompt") || "A futuristic city with flying cars"; - const size = searchParams.get("size") || "1024x1024"; - - try { - const imageData = await this.strategy.generateImage(prompt, size); - if (isURL(imageData)) { - return handleUrlResponse(imageData); - } else { - // Directly return image data as in ReplicateStrategy - return handleImageDataResponse(imageData); - } - } catch (error) { - console.error(error); - return new Response("Image generation failed.", { status: 500 }); - } - } - - return new Response("Not Found", { status: 404 }); - } -} - -class OpenAiStrategy { - constructor(env) { - this.env = env; - } - - async generateImage(prompt, size) { - this.openai = new OpenAI({ apiKey: env.OPENAI_API_KEY }); - const response = await this.openai.images.generate({ - model: this.env.IMAGE_MODEL, - prompt, - n: 1, - response_format: "url", - }); - return response.data[0].url; - } -} - -class ReplicateStrategy { - constructor(env) { - this.env = env; - } - - async generateImage(prompt, size) { - const replicate = new Replicate({ auth: this.env.REPLICATE_TOKEN }); - const output = await replicate.run(this.env.IMAGE_MODEL, { - input: { - prompt, - aspect_ratio: "1:1", - output_format: "webp", - output_quality: 100, - safety_tolerance: 2, - height: parseInt(size.split("x").at(0).replace("x", "")), - width: parseInt(size.split("x").at(1).replace("x", "")), - prompt_upsampling: true, - }, - }); - return output; - } -} - -function isURL(imageUrl) { - const urlPattern = - /^(https?:\/\/)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(:\d+)?(\/\S*)?$/; - return urlPattern.test(imageUrl); -} - -async function handleUrlResponse(iUrl) { - const imageResponse = await fetch(iUrl); - if (!imageResponse.ok) { - throw new Error(`Failed to fetch image: ${imageResponse.statusText}`); - } - const headers = new Headers(imageResponse.headers); - headers.set("Content-Disposition", `inline; filename="generated_image.png"`); - - return new Response(imageResponse.body, { - headers, - status: imageResponse.status, - }); -} - -async function handleImageDataResponse(imageData) { - const headers = new Headers(); - headers.set("Content-Type", "image/png"); - headers.set("Content-Disposition", `inline; filename="generated_image.png"`); - - return new Response(imageData, { headers, status: 200 }); -} diff --git a/workers/image-generation-service/wrangler-image-generation-service.toml b/workers/image-generation-service/wrangler-image-generation-service.toml deleted file mode 100644 index 2ccf0c5..0000000 --- a/workers/image-generation-service/wrangler-image-generation-service.toml +++ /dev/null @@ -1,16 +0,0 @@ -main="main.js" -name = "image-generation-service" -compatibility_date = "2024-12-20" -node_compat = true -dev.port = 3002 - -routes = [ - { pattern = "text2image.seemueller.io", custom_domain = true } -] - -[vars] -OPENAI_API_KEY = "" -OPENAI_API_ENDPOINT = "" -IMAGE_MODEL = "black-forest-labs/flux-1.1-pro" -REPLICATE_TOKEN = "" -TEXT2IMAGE_PROVIDER = "replicate" \ No newline at end of file diff --git a/workers/rate-limiter/index.ts b/workers/rate-limiter/index.ts deleted file mode 100644 index 23870f3..0000000 --- a/workers/rate-limiter/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -interface Env { - TEXT2IMAGE_RATE_LIMITER: any; -} - -export default { - async fetch(request, env): Promise { - const { pathname } = new URL(request.url); - - const { success } = await env.TEXT2IMAGE_RATE_LIMITER.limit({ - key: pathname, - }); - if (!success) { - const svg = ` - - - - Sorry! Rate limit exceeded, try again in a couple minutes. - - - `; - return new Response(svg, { - status: 429, - headers: { - "Content-Type": "image/svg+xml", - }, - }); - } - - return new Response(`Success!`); - }, -} satisfies ExportedHandler; diff --git a/workers/rate-limiter/wrangler-rate-limiter.toml b/workers/rate-limiter/wrangler-rate-limiter.toml deleted file mode 100644 index 435769b..0000000 --- a/workers/rate-limiter/wrangler-rate-limiter.toml +++ /dev/null @@ -1,22 +0,0 @@ -name = "rate-limiter" -main = "index.ts" -compatibility_date = "2024-12-20" -node_compat = true -dev.port = 3003 - -routes = [ - { pattern = "text2image.seemueller.io/generate*", zone_name = "seemueller.io" }, -] - -# The rate limiting API is in open beta. -[[unsafe.bindings]] -name = "TEXT2IMAGE_RATE_LIMITER" -type = "ratelimit" -# An identifier you define, that is unique to your Cloudflare account. -# Must be an integer. -namespace_id = "1001" - -# Limit: the number of requests allowed within a given period in a single -# Cloudflare location -# Period: the duration of the period, in seconds. Must be either 10 or 60 -simple = { limit = 26, period = 101} \ No newline at end of file diff --git a/wrangler.toml b/wrangler.toml index a45800c..bb4001a 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -14,26 +14,4 @@ preview_urls = false durable_objects.bindings = [{name = "SITE_COORDINATOR", class_name = "SiteCoordinator", script_name = "geoff-seemueller-io"}] migrations = [{tag = "v1", new_classes = ["SiteCoordinator"]}] kv_namespaces = [{binding = "KV_STORAGE", id = "placeholderId", preview_id = "placeholderIdPreview"}] -services = [{binding = "EMAIL_SERVICE", service = "email-service-rpc"}] - -# Dev configuration (remote) -[env.dev] -kv_namespaces = [{binding = "KV_STORAGE", id = "", preview_id = ""}] -durable_objects.bindings = [{name = "SITE_COORDINATOR", class_name = "SiteCoordinator", script_name = "geoff-seemueller-io-dev"}] -migrations = [{tag = "v1", new_classes = ["SiteCoordinator"]}] -services = [{binding = "EMAIL_SERVICE", service = "email-service-rpc"}] - - -# Staging configuration -[env.staging] -kv_namespaces = [{binding = "KV_STORAGE", id = "", preview_id = ""}] -durable_objects.bindings = [{name = "SITE_COORDINATOR", class_name = "SiteCoordinator", script_name = "geoff-seemueller-io-staging"}] -migrations = [{tag = "v1", new_classes = ["SiteCoordinator"]}] -services = [{binding = "EMAIL_SERVICE", service = "email-service-rpc"}] - -# Production configuration -[env.production] -kv_namespaces = [{binding = "KV_STORAGE", id = "", preview_id = ""}] -durable_objects.bindings = [{name = "SITE_COORDINATOR", class_name = "SiteCoordinator", script_name = "geoff-seemueller-io-production"}] -migrations = [{tag = "v1", new_classes = ["SiteCoordinator"]}] -services = [{binding = "EMAIL_SERVICE", service = "email-service-rpc"}] +services = [{binding = "EMAIL_SERVICE", service = "email-service-rpc"}] \ No newline at end of file