Upload 306 files
Browse files- .gitattributes +10 -0
- backend/__pycache__/main.cpython-312.pyc +0 -0
- backend/logs/app.log +178 -0
- backend/main.py +52 -3
- backend/routers/__pycache__/auth.cpython-312.pyc +0 -0
- backend/routers/__pycache__/openai_image.cpython-312.pyc +0 -0
- backend/routers/auth.py +40 -7
- backend/routers/openai_image.py +114 -4
- backend/services/__pycache__/openai_service.cpython-312.pyc +0 -0
- backend/services/openai_service.py +74 -94
- backend/uploads/0489e41ca42c4f62972f9df4048f4fee.jpg +0 -0
- backend/uploads/0d38e64424a44bfea0d2cd60b6ab7ca7.jpg +0 -0
- backend/uploads/44551e85423f44e28220e796e8aad972.jpg +0 -0
- backend/uploads/6aae686070084421be72844fcab3432c.jpg +0 -0
- backend/uploads/91484306cbd94cc187cf2666993e17fd.jpg +0 -0
- backend/uploads/977ec30d99304e2a95328c448b8e71f7.jpg +0 -0
- backend/uploads/99256e3e599c4ed0ab1cfb9ed3823137.jpg +0 -0
- backend/uploads/b60b62ea9b67460d9f192fc7e46f0017.jpg +0 -0
- backend/uploads/db11756ac9d04460a06785f066342331.jpg +0 -0
- backend/uploads/f652de6149aa4fd6a775c770e5736367.jpg +0 -0
- backend/uploads/f8a0db84234c426e9252ee65e958f77a.jpg +0 -0
- backend/uploads/generated/032d76c129a442cebeac3323bc4fc080.png +3 -0
- backend/uploads/generated/08a1798e9521455a902edda85dc029cc.png +3 -0
- backend/uploads/generated/1bc4caa711694fb8acca6b23159f754f.png +3 -0
- backend/uploads/generated/231900b690ad4adb9883a3d600716a7d.png +3 -0
- backend/uploads/generated/2a5b913b68a243379027cd01b187b4cd.png +3 -0
- backend/uploads/generated/2d6e02255c3a4f00804ace65c49f19aa.png +3 -0
- backend/uploads/generated/5b6f11b554f74c5486ce33e390f8c75d.png +3 -0
- backend/uploads/generated/836b20819d49430a9fc94c02e8e07885.png +3 -0
- backend/uploads/generated/d664c83e3b614760834cdaad28769340.png +3 -0
- backend/uploads/generated/dbd083972cf5430998885a9f7c36ac0a.png +3 -0
- frontend/dist/assets/index-CenEQfA2.css +1 -0
- frontend/dist/assets/index-DE9xapIa.js +0 -0
- frontend/dist/index.html +11 -4
- frontend/index.html +9 -2
- frontend/src/features/roomSetup/RoomSetup.tsx +19 -3
- frontend/src/features/roomSetup/roomSetupHooks.ts +17 -0
- frontend/src/features/roomVisualizer/RoomVisualizer.tsx +67 -1
- frontend/src/hooks/useApplyTexture.ts +21 -2
- frontend/src/version.ts +1 -1
.gitattributes
CHANGED
|
@@ -162,3 +162,13 @@ backend/uploads/acm[[:space:]]gris_edit_19d266a8.jpg filter=lfs diff=lfs merge=l
|
|
| 162 |
backend/uploads/acm[[:space:]]gris.jpg filter=lfs diff=lfs merge=lfs -text
|
| 163 |
backend/uploads/hyper-reality-1778254222964_edit_9c5de50a_edit_7e5043d5.jpg filter=lfs diff=lfs merge=lfs -text
|
| 164 |
backend/uploads/hyper-reality-1778254222964_edit_a92f4266_edit_161ee5c4.jpg filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
backend/uploads/acm[[:space:]]gris.jpg filter=lfs diff=lfs merge=lfs -text
|
| 163 |
backend/uploads/hyper-reality-1778254222964_edit_9c5de50a_edit_7e5043d5.jpg filter=lfs diff=lfs merge=lfs -text
|
| 164 |
backend/uploads/hyper-reality-1778254222964_edit_a92f4266_edit_161ee5c4.jpg filter=lfs diff=lfs merge=lfs -text
|
| 165 |
+
backend/uploads/generated/032d76c129a442cebeac3323bc4fc080.png filter=lfs diff=lfs merge=lfs -text
|
| 166 |
+
backend/uploads/generated/08a1798e9521455a902edda85dc029cc.png filter=lfs diff=lfs merge=lfs -text
|
| 167 |
+
backend/uploads/generated/1bc4caa711694fb8acca6b23159f754f.png filter=lfs diff=lfs merge=lfs -text
|
| 168 |
+
backend/uploads/generated/231900b690ad4adb9883a3d600716a7d.png filter=lfs diff=lfs merge=lfs -text
|
| 169 |
+
backend/uploads/generated/2a5b913b68a243379027cd01b187b4cd.png filter=lfs diff=lfs merge=lfs -text
|
| 170 |
+
backend/uploads/generated/2d6e02255c3a4f00804ace65c49f19aa.png filter=lfs diff=lfs merge=lfs -text
|
| 171 |
+
backend/uploads/generated/5b6f11b554f74c5486ce33e390f8c75d.png filter=lfs diff=lfs merge=lfs -text
|
| 172 |
+
backend/uploads/generated/836b20819d49430a9fc94c02e8e07885.png filter=lfs diff=lfs merge=lfs -text
|
| 173 |
+
backend/uploads/generated/d664c83e3b614760834cdaad28769340.png filter=lfs diff=lfs merge=lfs -text
|
| 174 |
+
backend/uploads/generated/dbd083972cf5430998885a9f7c36ac0a.png filter=lfs diff=lfs merge=lfs -text
|
backend/__pycache__/main.cpython-312.pyc
CHANGED
|
Binary files a/backend/__pycache__/main.cpython-312.pyc and b/backend/__pycache__/main.cpython-312.pyc differ
|
|
|
backend/logs/app.log
CHANGED
|
@@ -5026,3 +5026,181 @@ RuntimeError: Both Gradio Spaces failed.
|
|
| 5026 |
2026-05-11 18:47:40,240 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5027 |
2026-05-11 18:47:53,426 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0278b94a12dd2c11934074, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0278b94a12dd2c11934074"}, "remainingTimeMS": 30}
|
| 5028 |
2026-05-11 18:47:53,426 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0278b94a12dd2c11934074, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0278b94a12dd2c11934074"}, "remainingTimeMS": 30}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5026 |
2026-05-11 18:47:40,240 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5027 |
2026-05-11 18:47:53,426 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0278b94a12dd2c11934074, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0278b94a12dd2c11934074"}, "remainingTimeMS": 30}
|
| 5028 |
2026-05-11 18:47:53,426 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0278b94a12dd2c11934074, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0278b94a12dd2c11934074"}, "remainingTimeMS": 30}
|
| 5029 |
+
2026-05-11 19:06:05,368 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027cfda87b46fdcade70c0, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027cfda87b46fdcade70c0"}, "remainingTimeMS": 30}
|
| 5030 |
+
2026-05-11 19:06:12,738 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a027d04a87b46fdcade70c1, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027d04a87b46fdcade70c1"}, "remainingTimeMS": 30}
|
| 5031 |
+
2026-05-11 19:06:12,739 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a027d04a87b46fdcade70c1, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027d04a87b46fdcade70c1"}, "remainingTimeMS": 30}
|
| 5032 |
+
2026-05-11 19:08:06,520 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027d761ac5024147e14ddd, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027d761ac5024147e14ddd"}, "remainingTimeMS": 30}
|
| 5033 |
+
2026-05-11 19:08:47,155 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a027d9f1ac5024147e14dde, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027d9f1ac5024147e14dde"}, "remainingTimeMS": 30}
|
| 5034 |
+
2026-05-11 19:08:47,218 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a027d9f1ac5024147e14dde, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027d9f1ac5024147e14dde"}, "remainingTimeMS": 30}
|
| 5035 |
+
2026-05-11 19:09:25,574 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027dc593faabe7b94d01db, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027dc593faabe7b94d01db"}, "remainingTimeMS": 30}
|
| 5036 |
+
2026-05-11 19:09:28,759 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027dc83e594b87cb65fae1, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027dc83e594b87cb65fae1"}, "remainingTimeMS": 30}
|
| 5037 |
+
2026-05-11 19:11:42,248 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027e4e8ae5a4bdf2a01b4a, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027e4e8ae5a4bdf2a01b4a"}, "remainingTimeMS": 30}
|
| 5038 |
+
2026-05-11 19:11:45,646 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027e511d40e5545928f21a, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027e511d40e5545928f21a"}, "remainingTimeMS": 30}
|
| 5039 |
+
2026-05-11 19:12:29,155 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027e7d6b97ebcd8799b29a, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027e7d6b97ebcd8799b29a"}, "remainingTimeMS": 30}
|
| 5040 |
+
2026-05-11 19:12:32,505 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027e803a5d599a0d8af5ec, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027e803a5d599a0d8af5ec"}, "remainingTimeMS": 30}
|
| 5041 |
+
2026-05-11 19:12:38,840 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027e868bf43995e2ac9977, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027e868bf43995e2ac9977"}, "remainingTimeMS": 30}
|
| 5042 |
+
2026-05-11 19:15:15,838 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027f23949e3a6713885bd3, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027f23949e3a6713885bd3"}, "remainingTimeMS": 30}
|
| 5043 |
+
2026-05-11 19:15:16,974 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027f24949e3a6713885bd4, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027f24949e3a6713885bd4"}, "remainingTimeMS": 30}
|
| 5044 |
+
2026-05-11 19:15:51,653 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027f470f7d0c4f53d759f5, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027f470f7d0c4f53d759f5"}, "remainingTimeMS": 30}
|
| 5045 |
+
2026-05-11 19:15:52,590 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027f480f7d0c4f53d759f6, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027f480f7d0c4f53d759f6"}, "remainingTimeMS": 30}
|
| 5046 |
+
2026-05-11 19:17:39,169 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027fb35cc9f5b422b27472, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027fb35cc9f5b422b27472"}, "remainingTimeMS": 30}
|
| 5047 |
+
2026-05-11 19:17:40,232 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027fb45cc9f5b422b27473, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027fb45cc9f5b422b27473"}, "remainingTimeMS": 30}
|
| 5048 |
+
2026-05-11 19:17:43,584 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027fb7568814d4963dd0bb, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027fb7568814d4963dd0bb"}, "remainingTimeMS": 30}
|
| 5049 |
+
2026-05-11 19:17:44,583 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027fb8568814d4963dd0bc, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027fb8568814d4963dd0bc"}, "remainingTimeMS": 30}
|
| 5050 |
+
2026-05-11 19:18:49,835 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027ff9c4a2c8fb7771ae26, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027ff9c4a2c8fb7771ae26"}, "remainingTimeMS": 29}
|
| 5051 |
+
2026-05-11 19:18:51,007 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a027ffbc4a2c8fb7771ae27, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a027ffbc4a2c8fb7771ae27"}, "remainingTimeMS": 30}
|
| 5052 |
+
2026-05-11 19:19:00,509 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028004c4a2c8fb7771ae28, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028004c4a2c8fb7771ae28"}, "remainingTimeMS": 30}
|
| 5053 |
+
2026-05-11 19:19:34,358 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5054 |
+
2026-05-11 19:20:25,698 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5055 |
+
2026-05-11 19:23:23,468 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02810b6e10f71b8416429a, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02810b6e10f71b8416429a"}, "remainingTimeMS": 30}
|
| 5056 |
+
2026-05-11 19:23:24,520 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02810c6e10f71b8416429b, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02810c6e10f71b8416429b"}, "remainingTimeMS": 30}
|
| 5057 |
+
2026-05-11 19:25:05,589 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02817124161d08478a156b, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02817124161d08478a156b"}, "remainingTimeMS": 30}
|
| 5058 |
+
2026-05-11 19:25:06,714 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02817224161d08478a156c, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02817224161d08478a156c"}, "remainingTimeMS": 30}
|
| 5059 |
+
2026-05-11 19:25:28,914 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5060 |
+
2026-05-11 19:26:13,818 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5061 |
+
2026-05-11 19:26:21,775 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0281bd5ba8caf5a831ae90, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0281bd5ba8caf5a831ae90"}, "remainingTimeMS": 30}
|
| 5062 |
+
2026-05-11 19:26:22,789 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0281be5ba8caf5a831ae91, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0281be5ba8caf5a831ae91"}, "remainingTimeMS": 30}
|
| 5063 |
+
2026-05-11 19:36:28,448 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02841c703779c67f0d9b34, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02841c703779c67f0d9b34"}, "remainingTimeMS": 30}
|
| 5064 |
+
2026-05-11 19:36:29,570 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02841d703779c67f0d9b35, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02841d703779c67f0d9b35"}, "remainingTimeMS": 30}
|
| 5065 |
+
2026-05-11 19:36:33,261 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028421703779c67f0d9b36, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028421703779c67f0d9b36"}, "remainingTimeMS": 30}
|
| 5066 |
+
2026-05-11 19:36:33,261 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028421703779c67f0d9b36, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028421703779c67f0d9b36"}, "remainingTimeMS": 30}
|
| 5067 |
+
2026-05-11 19:37:02,209 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5068 |
+
2026-05-11 19:39:05,683 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0284b9c02b8a2b4c1fd305, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0284b9c02b8a2b4c1fd305"}, "remainingTimeMS": 30}
|
| 5069 |
+
2026-05-11 19:39:09,088 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0284bd757457c966632fb6, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0284bd757457c966632fb6"}, "remainingTimeMS": 30}
|
| 5070 |
+
2026-05-11 19:39:10,088 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0284be757457c966632fb7, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0284be757457c966632fb7"}, "remainingTimeMS": 30}
|
| 5071 |
+
2026-05-11 19:39:52,700 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0284e8757457c966632fb8, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0284e8757457c966632fb8"}, "remainingTimeMS": 30}
|
| 5072 |
+
2026-05-11 19:39:52,701 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0284e8757457c966632fb8, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0284e8757457c966632fb8"}, "remainingTimeMS": 30}
|
| 5073 |
+
2026-05-11 19:41:00,305 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02852c8a1367122245eccc, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02852c8a1367122245eccc"}, "remainingTimeMS": 30}
|
| 5074 |
+
2026-05-11 19:41:03,225 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02852f267122fd694f21e3, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02852f267122fd694f21e3"}, "remainingTimeMS": 30}
|
| 5075 |
+
2026-05-11 19:41:04,203 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028530267122fd694f21e4, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028530267122fd694f21e4"}, "remainingTimeMS": 30}
|
| 5076 |
+
2026-05-11 19:41:41,968 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0285554c2f7ccbf3415908, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0285554c2f7ccbf3415908"}, "remainingTimeMS": 30}
|
| 5077 |
+
2026-05-11 19:41:42,925 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0285564c2f7ccbf3415909, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0285564c2f7ccbf3415909"}, "remainingTimeMS": 30}
|
| 5078 |
+
2026-05-11 19:42:05,869 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02856dac866a27c0a614ce, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02856dac866a27c0a614ce"}, "remainingTimeMS": 30}
|
| 5079 |
+
2026-05-11 19:42:07,090 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02856fac866a27c0a614cf, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02856fac866a27c0a614cf"}, "remainingTimeMS": 30}
|
| 5080 |
+
2026-05-11 19:42:08,500 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028570ac866a27c0a614d0, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028570ac866a27c0a614d0"}, "remainingTimeMS": 30}
|
| 5081 |
+
2026-05-11 19:42:08,500 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028570ac866a27c0a614d0, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028570ac866a27c0a614d0"}, "remainingTimeMS": 30}
|
| 5082 |
+
2026-05-11 19:42:45,966 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02859572403ff4d0782b8b, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02859572403ff4d0782b8b"}, "remainingTimeMS": 30}
|
| 5083 |
+
2026-05-11 19:42:46,913 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02859672403ff4d0782b8c, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02859672403ff4d0782b8c"}, "remainingTimeMS": 30}
|
| 5084 |
+
2026-05-11 19:42:59,118 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0285a372403ff4d0782b8d, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0285a372403ff4d0782b8d"}, "remainingTimeMS": 30}
|
| 5085 |
+
2026-05-11 19:42:59,120 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0285a372403ff4d0782b8d, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0285a372403ff4d0782b8d"}, "remainingTimeMS": 30}
|
| 5086 |
+
2026-05-11 19:43:13,311 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5087 |
+
2026-05-11 19:43:33,906 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5088 |
+
2026-05-11 19:48:53,424 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028705348962251040020b, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028705348962251040020b"}, "remainingTimeMS": 30}
|
| 5089 |
+
2026-05-11 19:48:54,613 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028706348962251040020c, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028706348962251040020c"}, "remainingTimeMS": 30}
|
| 5090 |
+
2026-05-11 19:48:56,049 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028708348962251040020d, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028708348962251040020d"}, "remainingTimeMS": 30}
|
| 5091 |
+
2026-05-11 19:48:56,050 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028708348962251040020d, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028708348962251040020d"}, "remainingTimeMS": 30}
|
| 5092 |
+
2026-05-11 19:48:56,051 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028708348962251040020d, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028708348962251040020d"}, "remainingTimeMS": 30}
|
| 5093 |
+
2026-05-11 19:49:15,705 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5094 |
+
2026-05-11 19:49:38,447 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5095 |
+
2026-05-11 19:51:04,940 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0287887f7d678f206594ba, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0287887f7d678f206594ba"}, "remainingTimeMS": 30}
|
| 5096 |
+
2026-05-11 19:51:07,563 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02878bd029f8915c55e732, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02878bd029f8915c55e732"}, "remainingTimeMS": 30}
|
| 5097 |
+
2026-05-11 19:51:08,470 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02878cd029f8915c55e733, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02878cd029f8915c55e733"}, "remainingTimeMS": 30}
|
| 5098 |
+
2026-05-11 19:51:28,857 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5099 |
+
2026-05-11 19:51:49,286 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5100 |
+
2026-05-11 19:54:05,238 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02883d15dd6dc3e4f0f0b1, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02883d15dd6dc3e4f0f0b1"}, "remainingTimeMS": 30}
|
| 5101 |
+
2026-05-11 19:54:06,288 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02883e15dd6dc3e4f0f0b2, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02883e15dd6dc3e4f0f0b2"}, "remainingTimeMS": 30}
|
| 5102 |
+
2026-05-11 19:54:36,036 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02885c3027b040c1692ec0, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02885c3027b040c1692ec0"}, "remainingTimeMS": 30}
|
| 5103 |
+
2026-05-11 19:54:37,006 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02885d3027b040c1692ec1, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02885d3027b040c1692ec1"}, "remainingTimeMS": 30}
|
| 5104 |
+
2026-05-11 19:54:42,945 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0288623027b040c1692ec2, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0288623027b040c1692ec2"}, "remainingTimeMS": 30}
|
| 5105 |
+
2026-05-11 19:54:42,945 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0288623027b040c1692ec2, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0288623027b040c1692ec2"}, "remainingTimeMS": 30}
|
| 5106 |
+
2026-05-11 19:54:47,661 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5107 |
+
2026-05-11 19:55:09,379 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5108 |
+
2026-05-11 19:56:05,697 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0288b57400933c876eea54, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0288b57400933c876eea54"}, "remainingTimeMS": 30}
|
| 5109 |
+
2026-05-11 19:56:06,855 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0288b67400933c876eea55, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0288b67400933c876eea55"}, "remainingTimeMS": 30}
|
| 5110 |
+
2026-05-11 19:56:16,706 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0288c07400933c876eea56, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0288c07400933c876eea56"}, "remainingTimeMS": 30}
|
| 5111 |
+
2026-05-11 19:56:16,707 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0288c07400933c876eea56, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0288c07400933c876eea56"}, "remainingTimeMS": 30}
|
| 5112 |
+
2026-05-11 19:56:28,793 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0288ccf6c189e773fd6c5d, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0288ccf6c189e773fd6c5d"}, "remainingTimeMS": 30}
|
| 5113 |
+
2026-05-11 19:56:29,776 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0288cdf6c189e773fd6c5e, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0288cdf6c189e773fd6c5e"}, "remainingTimeMS": 30}
|
| 5114 |
+
2026-05-11 19:56:34,696 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5115 |
+
2026-05-11 19:56:59,964 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5116 |
+
2026-05-11 19:58:10,776 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028932e1953cbd31f51412, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028932e1953cbd31f51412"}, "remainingTimeMS": 30}
|
| 5117 |
+
2026-05-11 19:58:11,857 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028933e1953cbd31f51413, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028933e1953cbd31f51413"}, "remainingTimeMS": 30}
|
| 5118 |
+
2026-05-11 19:58:53,417 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02895dafb540fa4caa5bd7, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02895dafb540fa4caa5bd7"}, "remainingTimeMS": 30}
|
| 5119 |
+
2026-05-11 19:58:56,404 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0289608155a426c77e36e5, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0289608155a426c77e36e5"}, "remainingTimeMS": 30}
|
| 5120 |
+
2026-05-11 19:58:57,390 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0289618155a426c77e36e6, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0289618155a426c77e36e6"}, "remainingTimeMS": 30}
|
| 5121 |
+
2026-05-11 19:59:02,129 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0289668155a426c77e36e7, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0289668155a426c77e36e7"}, "remainingTimeMS": 30}
|
| 5122 |
+
2026-05-11 19:59:02,130 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a0289668155a426c77e36e7, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0289668155a426c77e36e7"}, "remainingTimeMS": 30}
|
| 5123 |
+
2026-05-11 19:59:07,982 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5124 |
+
2026-05-11 19:59:08,264 INFO backend.segmentation: OpenAI prompt length=919
|
| 5125 |
+
2026-05-11 19:59:28,536 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5126 |
+
2026-05-11 20:00:00,304 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0289a0d1507d375ff12f71, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0289a0d1507d375ff12f71"}, "remainingTimeMS": 30}
|
| 5127 |
+
2026-05-11 20:00:01,492 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a0289a1d1507d375ff12f72, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0289a1d1507d375ff12f72"}, "remainingTimeMS": 30}
|
| 5128 |
+
2026-05-11 20:00:04,295 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5129 |
+
2026-05-11 20:00:28,052 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5130 |
+
2026-05-11 20:00:28,570 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5131 |
+
2026-05-11 20:00:43,336 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5132 |
+
2026-05-11 20:01:48,552 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5133 |
+
2026-05-11 20:02:03,110 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5134 |
+
2026-05-11 20:03:03,014 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028a578f37a4f8e8d7d66c, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028a578f37a4f8e8d7d66c"}, "remainingTimeMS": 30}
|
| 5135 |
+
2026-05-11 20:03:04,041 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028a588f37a4f8e8d7d66d, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028a588f37a4f8e8d7d66d"}, "remainingTimeMS": 30}
|
| 5136 |
+
2026-05-11 20:03:05,250 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028a598f37a4f8e8d7d66e, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028a598f37a4f8e8d7d66e"}, "remainingTimeMS": 30}
|
| 5137 |
+
2026-05-11 20:03:05,250 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028a598f37a4f8e8d7d66e, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028a598f37a4f8e8d7d66e"}, "remainingTimeMS": 30}
|
| 5138 |
+
2026-05-11 20:03:16,863 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5139 |
+
2026-05-11 20:03:31,328 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5140 |
+
2026-05-11 20:04:42,487 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5141 |
+
2026-05-11 20:04:58,256 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5142 |
+
2026-05-11 20:06:22,491 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028b1ebc16a0851415bf50, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028b1ebc16a0851415bf50"}, "remainingTimeMS": 29}
|
| 5143 |
+
2026-05-11 20:06:23,537 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028b1fbc16a0851415bf51, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028b1fbc16a0851415bf51"}, "remainingTimeMS": 30}
|
| 5144 |
+
2026-05-11 20:06:47,110 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028b37a802942fd2594f91, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028b37a802942fd2594f91"}, "remainingTimeMS": 30}
|
| 5145 |
+
2026-05-11 20:06:49,908 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028b397b0f25a542e65c27, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028b397b0f25a542e65c27"}, "remainingTimeMS": 30}
|
| 5146 |
+
2026-05-11 20:06:50,920 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028b3a7b0f25a542e65c28, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028b3a7b0f25a542e65c28"}, "remainingTimeMS": 30}
|
| 5147 |
+
2026-05-11 20:11:50,807 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028c66b34267fbde5b34af, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028c66b34267fbde5b34af"}, "remainingTimeMS": 30}
|
| 5148 |
+
2026-05-11 20:11:51,851 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028c67b34267fbde5b34b0, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028c67b34267fbde5b34b0"}, "remainingTimeMS": 30}
|
| 5149 |
+
2026-05-11 20:13:05,234 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028cb1215d719b596e53d7, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028cb1215d719b596e53d7"}, "remainingTimeMS": 30}
|
| 5150 |
+
2026-05-11 20:13:06,341 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028cb2215d719b596e53d8, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028cb2215d719b596e53d8"}, "remainingTimeMS": 30}
|
| 5151 |
+
2026-05-11 20:15:36,865 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028d488e96660a60b8cfc4, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028d488e96660a60b8cfc4"}, "remainingTimeMS": 30}
|
| 5152 |
+
2026-05-11 20:15:37,926 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028d498e96660a60b8cfc5, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028d498e96660a60b8cfc5"}, "remainingTimeMS": 30}
|
| 5153 |
+
2026-05-11 20:15:39,983 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028d4b8e96660a60b8cfc6, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028d4b8e96660a60b8cfc6"}, "remainingTimeMS": 30}
|
| 5154 |
+
2026-05-11 20:15:39,983 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028d4b8e96660a60b8cfc6, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028d4b8e96660a60b8cfc6"}, "remainingTimeMS": 30}
|
| 5155 |
+
2026-05-11 20:15:47,786 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5156 |
+
2026-05-11 20:16:09,295 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5157 |
+
2026-05-11 20:16:09,669 INFO backend.segmentation: Saved generated image to C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\generated\2d6e02255c3a4f00804ace65c49f19aa.png
|
| 5158 |
+
2026-05-11 20:16:09,844 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "<function writable_server_selector at 0x0000029BEA759D00>", "operation": "update", "topologyDescription": "<TopologyDescription id: 6a028d698e96660a60b8cfc7, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028d698e96660a60b8cfc7"}, "remainingTimeMS": 30}
|
| 5159 |
+
2026-05-11 20:20:08,586 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028e58878a8628bfee7a9c, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028e58878a8628bfee7a9c"}, "remainingTimeMS": 30}
|
| 5160 |
+
2026-05-11 20:20:09,725 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028e59878a8628bfee7a9d, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028e59878a8628bfee7a9d"}, "remainingTimeMS": 30}
|
| 5161 |
+
2026-05-11 20:20:11,253 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028e5b878a8628bfee7a9e, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028e5b878a8628bfee7a9e"}, "remainingTimeMS": 30}
|
| 5162 |
+
2026-05-11 20:20:11,255 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028e5b878a8628bfee7a9e, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028e5b878a8628bfee7a9e"}, "remainingTimeMS": 30}
|
| 5163 |
+
2026-05-11 20:20:16,995 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5164 |
+
2026-05-11 20:20:33,482 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5165 |
+
2026-05-11 20:20:34,342 INFO backend.segmentation: Saved generated image to C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\generated\231900b690ad4adb9883a3d600716a7d.png
|
| 5166 |
+
2026-05-11 20:20:34,542 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "<function writable_server_selector at 0x000001E117FD9D00>", "operation": "update", "topologyDescription": "<TopologyDescription id: 6a028e72878a8628bfee7a9f, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028e72878a8628bfee7a9f"}, "remainingTimeMS": 30}
|
| 5167 |
+
2026-05-11 20:20:46,915 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5168 |
+
2026-05-11 20:21:02,580 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5169 |
+
2026-05-11 20:21:02,987 INFO backend.segmentation: Saved generated image to C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\generated\d664c83e3b614760834cdaad28769340.png
|
| 5170 |
+
2026-05-11 20:21:03,168 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "<function writable_server_selector at 0x000001E117FD9D00>", "operation": "update", "topologyDescription": "<TopologyDescription id: 6a028e8f878a8628bfee7aa0, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028e8f878a8628bfee7aa0"}, "remainingTimeMS": 30}
|
| 5171 |
+
2026-05-11 20:24:43,167 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028f6bdd1d2a0373a94f3c, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028f6bdd1d2a0373a94f3c"}, "remainingTimeMS": 30}
|
| 5172 |
+
2026-05-11 20:24:46,257 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028f6ef42c431356712eb2, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028f6ef42c431356712eb2"}, "remainingTimeMS": 30}
|
| 5173 |
+
2026-05-11 20:24:47,309 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a028f6ff42c431356712eb3, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028f6ff42c431356712eb3"}, "remainingTimeMS": 30}
|
| 5174 |
+
2026-05-11 20:24:48,513 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028f70f42c431356712eb4, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028f70f42c431356712eb4"}, "remainingTimeMS": 30}
|
| 5175 |
+
2026-05-11 20:24:48,514 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a028f70f42c431356712eb4, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028f70f42c431356712eb4"}, "remainingTimeMS": 30}
|
| 5176 |
+
2026-05-11 20:24:50,217 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5177 |
+
2026-05-11 20:25:09,782 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5178 |
+
2026-05-11 20:25:10,153 INFO backend.segmentation: Saved generated image to C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\generated\5b6f11b554f74c5486ce33e390f8c75d.png
|
| 5179 |
+
2026-05-11 20:25:10,323 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "<function writable_server_selector at 0x000001B7BDBC9D00>", "operation": "update", "topologyDescription": "<TopologyDescription id: 6a028f86f42c431356712eb5, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028f86f42c431356712eb5"}, "remainingTimeMS": 30}
|
| 5180 |
+
2026-05-11 20:26:39,620 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5181 |
+
2026-05-11 20:27:01,355 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5182 |
+
2026-05-11 20:27:01,729 INFO backend.segmentation: Saved generated image to C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\generated\032d76c129a442cebeac3323bc4fc080.png
|
| 5183 |
+
2026-05-11 20:27:01,908 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "<function writable_server_selector at 0x000001B7BDBC9D00>", "operation": "update", "topologyDescription": "<TopologyDescription id: 6a028ff5f42c431356712eb6, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a028ff5f42c431356712eb6"}, "remainingTimeMS": 30}
|
| 5184 |
+
2026-05-11 20:27:10,935 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5185 |
+
2026-05-11 20:27:31,741 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5186 |
+
2026-05-11 20:27:32,280 INFO backend.segmentation: Saved generated image to C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\generated\08a1798e9521455a902edda85dc029cc.png
|
| 5187 |
+
2026-05-11 20:27:32,545 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "<function writable_server_selector at 0x000001B7BDBC9D00>", "operation": "update", "topologyDescription": "<TopologyDescription id: 6a029014f42c431356712eb7, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a029014f42c431356712eb7"}, "remainingTimeMS": 30}
|
| 5188 |
+
2026-05-11 20:27:58,182 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5189 |
+
2026-05-11 20:28:46,217 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5190 |
+
2026-05-11 20:28:46,940 INFO backend.segmentation: Saved generated image to C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\generated\1bc4caa711694fb8acca6b23159f754f.png
|
| 5191 |
+
2026-05-11 20:28:47,112 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "<function writable_server_selector at 0x000001B7BDBC9D00>", "operation": "update", "topologyDescription": "<TopologyDescription id: 6a02905ff42c431356712eb8, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02905ff42c431356712eb8"}, "remainingTimeMS": 30}
|
| 5192 |
+
2026-05-11 20:29:03,508 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5193 |
+
2026-05-11 20:29:44,213 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5194 |
+
2026-05-11 20:29:44,750 INFO backend.segmentation: Saved generated image to C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\generated\2a5b913b68a243379027cd01b187b4cd.png
|
| 5195 |
+
2026-05-11 20:29:44,955 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "<function writable_server_selector at 0x000001B7BDBC9D00>", "operation": "update", "topologyDescription": "<TopologyDescription id: 6a029098f42c431356712eb9, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a029098f42c431356712eb9"}, "remainingTimeMS": 30}
|
| 5196 |
+
2026-05-11 20:29:53,559 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5197 |
+
2026-05-11 20:30:37,983 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5198 |
+
2026-05-11 20:30:38,490 INFO backend.segmentation: Saved generated image to C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\generated\836b20819d49430a9fc94c02e8e07885.png
|
| 5199 |
+
2026-05-11 20:30:38,711 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "<function writable_server_selector at 0x000001B7BDBC9D00>", "operation": "update", "topologyDescription": "<TopologyDescription id: 6a0290cef42c431356712eba, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a0290cef42c431356712eba"}, "remainingTimeMS": 30}
|
| 5200 |
+
2026-05-11 21:01:35,945 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a02980ff2c1d98dfeb7f208, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02980ff2c1d98dfeb7f208"}, "remainingTimeMS": 30}
|
| 5201 |
+
2026-05-11 21:01:37,029 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "count", "topologyDescription": "<TopologyDescription id: 6a029811f2c1d98dfeb7f209, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a029811f2c1d98dfeb7f209"}, "remainingTimeMS": 30}
|
| 5202 |
+
2026-05-11 21:01:40,034 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "Primary()", "operation": "find", "topologyDescription": "<TopologyDescription id: 6a029814f2c1d98dfeb7f20a, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a029814f2c1d98dfeb7f20a"}, "remainingTimeMS": 30}
|
| 5203 |
+
2026-05-11 21:01:47,994 INFO backend.segmentation: /api/generate-image received file: hyper-reality-1778254222964.jpg (84903 bytes)
|
| 5204 |
+
2026-05-11 21:02:33,393 INFO httpx: HTTP Request: POST https://api.openai.com/v1/images/edits "HTTP/1.1 200 OK"
|
| 5205 |
+
2026-05-11 21:02:34,216 INFO backend.segmentation: Saved generated image to C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\generated\dbd083972cf5430998885a9f7c36ac0a.png
|
| 5206 |
+
2026-05-11 21:02:34,417 INFO pymongo.serverSelection: {"message": "Waiting for suitable server to become available", "selector": "<function writable_server_selector at 0x000001F9459E9D00>", "operation": "update", "topologyDescription": "<TopologyDescription id: 6a02984af2c1d98dfeb7f20b, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('ac-tynjizz-shard-00-00.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-01.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>, <ServerDescription ('ac-tynjizz-shard-00-02.n9htwoa.mongodb.net', 27017) server_type: Unknown, rtt: None>]>", "clientId": {"$oid": "6a02984af2c1d98dfeb7f20b"}, "remainingTimeMS": 30}
|
backend/main.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
import mimetypes
|
| 2 |
import os
|
| 3 |
import subprocess
|
|
|
|
| 4 |
import threading
|
| 5 |
import time
|
| 6 |
from pathlib import Path
|
|
@@ -9,6 +10,7 @@ from dotenv import load_dotenv
|
|
| 9 |
load_dotenv(Path(__file__).resolve().parent / ".env")
|
| 10 |
|
| 11 |
from fastapi import FastAPI, Request
|
|
|
|
| 12 |
from fastapi.middleware.cors import CORSMiddleware
|
| 13 |
from fastapi.staticfiles import StaticFiles
|
| 14 |
|
|
@@ -45,6 +47,9 @@ async def remove_x_frame_options(request: Request, call_next):
|
|
| 45 |
# Comentamos las demás inclusiones para deshabilitar funcionalidades
|
| 46 |
# posteriores (segmentación, inpainting, sesiones, catálogo, etc.).
|
| 47 |
# Re-activar routers necesarios para el frontend
|
|
|
|
|
|
|
|
|
|
| 48 |
app.include_router(sessions.router)
|
| 49 |
app.include_router(segmentation.router)
|
| 50 |
app.include_router(openai_image.router)
|
|
@@ -60,8 +65,37 @@ UPLOADS_DIR.mkdir(parents=True, exist_ok=True)
|
|
| 60 |
app.mount("/uploads", StaticFiles(directory=UPLOADS_DIR), name="uploads")
|
| 61 |
|
| 62 |
if (FRONTEND_DIST / "index.html").exists():
|
| 63 |
-
#
|
| 64 |
-
app.mount("/", StaticFiles(directory=FRONTEND_DIST, html=True), name="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
|
| 66 |
|
| 67 |
# Frontend watcher (development helper)
|
|
@@ -85,8 +119,23 @@ def scan_frontend_sources() -> dict:
|
|
| 85 |
def run_frontend_build() -> None:
|
| 86 |
if not FRONTEND_DIR.exists():
|
| 87 |
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
print("[backend] Ejecutando build del frontend...")
|
| 89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
if result.returncode != 0:
|
| 91 |
print("[backend] Build falló:")
|
| 92 |
print(result.stdout)
|
|
|
|
| 1 |
import mimetypes
|
| 2 |
import os
|
| 3 |
import subprocess
|
| 4 |
+
import shutil
|
| 5 |
import threading
|
| 6 |
import time
|
| 7 |
from pathlib import Path
|
|
|
|
| 10 |
load_dotenv(Path(__file__).resolve().parent / ".env")
|
| 11 |
|
| 12 |
from fastapi import FastAPI, Request
|
| 13 |
+
from fastapi.responses import RedirectResponse, FileResponse
|
| 14 |
from fastapi.middleware.cors import CORSMiddleware
|
| 15 |
from fastapi.staticfiles import StaticFiles
|
| 16 |
|
|
|
|
| 47 |
# Comentamos las demás inclusiones para deshabilitar funcionalidades
|
| 48 |
# posteriores (segmentación, inpainting, sesiones, catálogo, etc.).
|
| 49 |
# Re-activar routers necesarios para el frontend
|
| 50 |
+
app.include_router(auth.router)
|
| 51 |
+
app.include_router(media.router)
|
| 52 |
+
app.include_router(pages.router)
|
| 53 |
app.include_router(sessions.router)
|
| 54 |
app.include_router(segmentation.router)
|
| 55 |
app.include_router(openai_image.router)
|
|
|
|
| 65 |
app.mount("/uploads", StaticFiles(directory=UPLOADS_DIR), name="uploads")
|
| 66 |
|
| 67 |
if (FRONTEND_DIST / "index.html").exists():
|
| 68 |
+
# Montar la SPA únicamente en /app (el servidor tiene su propia landing en /)
|
| 69 |
+
app.mount("/app", StaticFiles(directory=FRONTEND_DIST, html=True), name="frontend_app")
|
| 70 |
+
# También exponer los assets estáticos en la raíz /assets para que los
|
| 71 |
+
# archivos generados por Vite (con rutas absolutas `/assets/...`) sean
|
| 72 |
+
# resueltos correctamente cuando la SPA se carga desde /app.
|
| 73 |
+
assets_dir = FRONTEND_DIST / "assets"
|
| 74 |
+
if assets_dir.exists():
|
| 75 |
+
app.mount("/assets", StaticFiles(directory=assets_dir), name="frontend_assets")
|
| 76 |
+
# Servir manifest y favicon desde el dist para PWA/links absolutos
|
| 77 |
+
manifest = FRONTEND_DIST / "manifest.json"
|
| 78 |
+
favicon = FRONTEND_DIST / "favicon.svg"
|
| 79 |
+
if manifest.exists():
|
| 80 |
+
@app.get("/manifest.json")
|
| 81 |
+
async def _manifest():
|
| 82 |
+
return FileResponse(str(manifest), media_type="application/manifest+json")
|
| 83 |
+
if favicon.exists():
|
| 84 |
+
@app.get("/favicon.svg")
|
| 85 |
+
async def _favicon():
|
| 86 |
+
return FileResponse(str(favicon), media_type="image/svg+xml")
|
| 87 |
+
|
| 88 |
+
# Ruta raíz: servir `backend/home.html` cuando exista (landing del servidor)
|
| 89 |
+
HOME_HTML = BASE_DIR / "home.html"
|
| 90 |
+
if HOME_HTML.exists():
|
| 91 |
+
@app.get("/")
|
| 92 |
+
async def _root_home():
|
| 93 |
+
return FileResponse(str(HOME_HTML), media_type="text/html")
|
| 94 |
+
else:
|
| 95 |
+
# Si no existe `home.html`, redirigimos a la SPA en /app
|
| 96 |
+
@app.get("/")
|
| 97 |
+
async def _root_redirect():
|
| 98 |
+
return RedirectResponse(url="/app")
|
| 99 |
|
| 100 |
|
| 101 |
# Frontend watcher (development helper)
|
|
|
|
| 119 |
def run_frontend_build() -> None:
|
| 120 |
if not FRONTEND_DIR.exists():
|
| 121 |
return
|
| 122 |
+
# Allow disabling automatic frontend builds (useful in production or CI without Node installed)
|
| 123 |
+
if os.getenv("SKIP_FRONTEND_BUILD", "").lower() in {"1", "true", "yes"}:
|
| 124 |
+
print("[backend] SKIP_FRONTEND_BUILD is set — skipping frontend build.")
|
| 125 |
+
return
|
| 126 |
+
|
| 127 |
+
npm_path = shutil.which("npm")
|
| 128 |
+
if not npm_path:
|
| 129 |
+
print("[backend] npm not found in PATH — skipping frontend build. Install Node.js/npm to enable auto-build or set SKIP_FRONTEND_BUILD=1 to disable this message.")
|
| 130 |
+
return
|
| 131 |
+
|
| 132 |
print("[backend] Ejecutando build del frontend...")
|
| 133 |
+
try:
|
| 134 |
+
result = subprocess.run([npm_path, "run", "build"], cwd=str(FRONTEND_DIR), capture_output=True, text=True)
|
| 135 |
+
except FileNotFoundError:
|
| 136 |
+
print("[backend] Error: npm executable not found when attempting to run build. Skipping frontend build.")
|
| 137 |
+
return
|
| 138 |
+
|
| 139 |
if result.returncode != 0:
|
| 140 |
print("[backend] Build falló:")
|
| 141 |
print(result.stdout)
|
backend/routers/__pycache__/auth.cpython-312.pyc
CHANGED
|
Binary files a/backend/routers/__pycache__/auth.cpython-312.pyc and b/backend/routers/__pycache__/auth.cpython-312.pyc differ
|
|
|
backend/routers/__pycache__/openai_image.cpython-312.pyc
CHANGED
|
Binary files a/backend/routers/__pycache__/openai_image.cpython-312.pyc and b/backend/routers/__pycache__/openai_image.cpython-312.pyc differ
|
|
|
backend/routers/auth.py
CHANGED
|
@@ -21,7 +21,7 @@ def _get_col():
|
|
| 21 |
global _client, _db, _col
|
| 22 |
if _col is None:
|
| 23 |
if not MONGODB_URI:
|
| 24 |
-
|
| 25 |
_client = AsyncIOMotorClient(MONGODB_URI)
|
| 26 |
_db = _client["hyper_reality"]
|
| 27 |
_col = _db["clients"]
|
|
@@ -87,6 +87,14 @@ async def startup():
|
|
| 87 |
|
| 88 |
@router.post("/api/token")
|
| 89 |
async def token(client_id: str = Form(...)):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
col = _get_col()
|
| 91 |
doc = await col.find_one({"_id": client_id})
|
| 92 |
if not doc:
|
|
@@ -103,10 +111,13 @@ async def config(client_id: str = Query(None), token: str = Query(None)):
|
|
| 103 |
return JSONResponse(content={"error": "token inválido o expirado"}, status_code=401)
|
| 104 |
if not client_id:
|
| 105 |
return JSONResponse(content={"error": "client_id o token requerido"}, status_code=400)
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
| 110 |
datos.pop("_id", None)
|
| 111 |
ACTIVE_SESSIONS[client_id] = _now_iso()
|
| 112 |
return JSONResponse(content={"client_id": client_id, **datos})
|
|
@@ -126,6 +137,18 @@ async def session_start(client_id: str = Form(None), token: str = Form(None)):
|
|
| 126 |
|
| 127 |
@router.get("/api/keys")
|
| 128 |
async def api_keys():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
col = _get_col()
|
| 130 |
docs = await col.find({}).to_list(length=500)
|
| 131 |
keys = [
|
|
@@ -144,8 +167,11 @@ async def api_keys():
|
|
| 144 |
async def generate_key(request: Request, nombre: str = Form(...), color_primario: str = Form("#8b5cf6")):
|
| 145 |
new_key = f"CLIENTE_{uuid4().hex[:8].upper()}"
|
| 146 |
doc = {"_id": new_key, "nombre": nombre, "color_primario": color_primario, "created_at": _now_iso()}
|
| 147 |
-
|
| 148 |
-
|
|
|
|
|
|
|
|
|
|
| 149 |
base_url = str(request.base_url).rstrip("/")
|
| 150 |
if request.headers.get("x-forwarded-proto") == "https" and base_url.startswith("http://"):
|
| 151 |
base_url = "https://" + base_url[7:]
|
|
@@ -164,6 +190,13 @@ async def generate_key(request: Request, nombre: str = Form(...), color_primario
|
|
| 164 |
|
| 165 |
@router.delete("/api/keys/{client_id}")
|
| 166 |
async def delete_key(client_id: str):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
col = _get_col()
|
| 168 |
result = await col.delete_one({"_id": client_id})
|
| 169 |
if result.deleted_count == 0:
|
|
|
|
| 21 |
global _client, _db, _col
|
| 22 |
if _col is None:
|
| 23 |
if not MONGODB_URI:
|
| 24 |
+
return None
|
| 25 |
_client = AsyncIOMotorClient(MONGODB_URI)
|
| 26 |
_db = _client["hyper_reality"]
|
| 27 |
_col = _db["clients"]
|
|
|
|
| 87 |
|
| 88 |
@router.post("/api/token")
|
| 89 |
async def token(client_id: str = Form(...)):
|
| 90 |
+
if not MONGODB_URI:
|
| 91 |
+
# fallback in-memory lookup
|
| 92 |
+
doc = next((c for c in _DEFAULT_CLIENTS if c["_id"] == client_id), None)
|
| 93 |
+
if not doc:
|
| 94 |
+
return JSONResponse(content={"error": "client_id inválido"}, status_code=400)
|
| 95 |
+
tok = generate_token_for_client(client_id)
|
| 96 |
+
return JSONResponse(content={"token": tok, "expires_in": TOKEN_TTL})
|
| 97 |
+
|
| 98 |
col = _get_col()
|
| 99 |
doc = await col.find_one({"_id": client_id})
|
| 100 |
if not doc:
|
|
|
|
| 111 |
return JSONResponse(content={"error": "token inválido o expirado"}, status_code=401)
|
| 112 |
if not client_id:
|
| 113 |
return JSONResponse(content={"error": "client_id o token requerido"}, status_code=400)
|
| 114 |
+
if not MONGODB_URI:
|
| 115 |
+
doc = next((c for c in _DEFAULT_CLIENTS if c["_id"] == client_id), None)
|
| 116 |
+
datos = doc or {"nombre": "Cliente Desconocido", "color_primario": "#f97316", "created_at": _now_iso()}
|
| 117 |
+
else:
|
| 118 |
+
col = _get_col()
|
| 119 |
+
doc = await col.find_one({"_id": client_id})
|
| 120 |
+
datos = doc or {"nombre": "Cliente Desconocido", "color_primario": "#f97316", "created_at": _now_iso()}
|
| 121 |
datos.pop("_id", None)
|
| 122 |
ACTIVE_SESSIONS[client_id] = _now_iso()
|
| 123 |
return JSONResponse(content={"client_id": client_id, **datos})
|
|
|
|
| 137 |
|
| 138 |
@router.get("/api/keys")
|
| 139 |
async def api_keys():
|
| 140 |
+
if not MONGODB_URI:
|
| 141 |
+
keys = [
|
| 142 |
+
{
|
| 143 |
+
"client_id": d["_id"],
|
| 144 |
+
"nombre": d.get("nombre", ""),
|
| 145 |
+
"color_primario": d.get("color_primario", ""),
|
| 146 |
+
"created_at": d.get("created_at", ""),
|
| 147 |
+
}
|
| 148 |
+
for d in _DEFAULT_CLIENTS
|
| 149 |
+
]
|
| 150 |
+
return JSONResponse(content={"keys": keys, "count": len(keys)})
|
| 151 |
+
|
| 152 |
col = _get_col()
|
| 153 |
docs = await col.find({}).to_list(length=500)
|
| 154 |
keys = [
|
|
|
|
| 167 |
async def generate_key(request: Request, nombre: str = Form(...), color_primario: str = Form("#8b5cf6")):
|
| 168 |
new_key = f"CLIENTE_{uuid4().hex[:8].upper()}"
|
| 169 |
doc = {"_id": new_key, "nombre": nombre, "color_primario": color_primario, "created_at": _now_iso()}
|
| 170 |
+
if not MONGODB_URI:
|
| 171 |
+
_DEFAULT_CLIENTS.append(doc)
|
| 172 |
+
else:
|
| 173 |
+
col = _get_col()
|
| 174 |
+
await col.insert_one(doc)
|
| 175 |
base_url = str(request.base_url).rstrip("/")
|
| 176 |
if request.headers.get("x-forwarded-proto") == "https" and base_url.startswith("http://"):
|
| 177 |
base_url = "https://" + base_url[7:]
|
|
|
|
| 190 |
|
| 191 |
@router.delete("/api/keys/{client_id}")
|
| 192 |
async def delete_key(client_id: str):
|
| 193 |
+
if not MONGODB_URI:
|
| 194 |
+
before = len(_DEFAULT_CLIENTS)
|
| 195 |
+
_DEFAULT_CLIENTS[:] = [c for c in _DEFAULT_CLIENTS if c["_id"] != client_id]
|
| 196 |
+
if len(_DEFAULT_CLIENTS) == before:
|
| 197 |
+
return JSONResponse(content={"error": "client_id no encontrado"}, status_code=404)
|
| 198 |
+
return JSONResponse(content={"status": "eliminado", "client_id": client_id})
|
| 199 |
+
|
| 200 |
col = _get_col()
|
| 201 |
result = await col.delete_one({"_id": client_id})
|
| 202 |
if result.deleted_count == 0:
|
backend/routers/openai_image.py
CHANGED
|
@@ -1,32 +1,142 @@
|
|
| 1 |
from fastapi import APIRouter, File, Form, HTTPException, UploadFile
|
|
|
|
| 2 |
from fastapi.responses import JSONResponse
|
| 3 |
from PIL import Image
|
| 4 |
import io
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
from services.openai_service import generate_image_with_openai
|
|
|
|
| 7 |
|
| 8 |
router = APIRouter()
|
| 9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
@router.post("/api/generate-image")
|
| 12 |
async def generate_image_endpoint(
|
| 13 |
-
file: UploadFile = File(
|
|
|
|
|
|
|
| 14 |
texture: str = Form(...),
|
| 15 |
api_key: str | None = Form(None),
|
| 16 |
preserve: int | None = Form(0),
|
|
|
|
| 17 |
):
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
try:
|
| 22 |
-
contents = await file.read()
|
| 23 |
pil = Image.open(io.BytesIO(contents)).convert("RGB")
|
| 24 |
except Exception:
|
| 25 |
raise HTTPException(status_code=400, detail="No se pudo leer la imagen subida")
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
png_bytes, msg = generate_image_with_openai(api_key, pil, texture, preserve)
|
| 28 |
if png_bytes is None:
|
| 29 |
raise HTTPException(status_code=500, detail=msg)
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
b64 = __import__("base64").b64encode(png_bytes).decode("ascii")
|
| 32 |
return JSONResponse(content={"result_b64": b64, "message": msg})
|
|
|
|
| 1 |
from fastapi import APIRouter, File, Form, HTTPException, UploadFile
|
| 2 |
+
from pathlib import Path
|
| 3 |
from fastapi.responses import JSONResponse
|
| 4 |
from PIL import Image
|
| 5 |
import io
|
| 6 |
+
import base64
|
| 7 |
+
import os
|
| 8 |
+
from uuid import uuid4
|
| 9 |
+
from motor.motor_asyncio import AsyncIOMotorClient
|
| 10 |
|
| 11 |
from services.openai_service import generate_image_with_openai
|
| 12 |
+
from core.config import logger
|
| 13 |
|
| 14 |
router = APIRouter()
|
| 15 |
|
| 16 |
+
BASE_DIR = Path(__file__).resolve().parent.parent
|
| 17 |
+
UPLOADS_DIR = BASE_DIR / "uploads"
|
| 18 |
+
GENERATED_DIR = UPLOADS_DIR / "generated"
|
| 19 |
+
GENERATED_DIR.mkdir(parents=True, exist_ok=True)
|
| 20 |
+
MONGODB_URI = os.getenv("MONGODB_URI", "")
|
| 21 |
+
|
| 22 |
|
| 23 |
@router.post("/api/generate-image")
|
| 24 |
async def generate_image_endpoint(
|
| 25 |
+
file: UploadFile | None = File(None),
|
| 26 |
+
image_b64: str | None = Form(None),
|
| 27 |
+
source_filename: str | None = Form(None),
|
| 28 |
texture: str = Form(...),
|
| 29 |
api_key: str | None = Form(None),
|
| 30 |
preserve: int | None = Form(0),
|
| 31 |
+
user_id: str | None = Form(None),
|
| 32 |
):
|
| 33 |
+
# Accept either a multipart file upload (`file`), a server-side filename (`source_filename`),
|
| 34 |
+
# or a base64 string in `image_b64`.
|
| 35 |
+
contents: bytes | None = None
|
| 36 |
+
# If a source_filename was provided, try to read it from the uploads dir and prefer it.
|
| 37 |
+
if source_filename:
|
| 38 |
+
# Accept either bare filename or path containing '/uploads/<filename>'
|
| 39 |
+
name = source_filename.split("/uploads/")[-1]
|
| 40 |
+
candidate = UPLOADS_DIR / name
|
| 41 |
+
if candidate.exists():
|
| 42 |
+
try:
|
| 43 |
+
contents = candidate.read_bytes()
|
| 44 |
+
logger.info("/api/generate-image using server upload file: %s", str(candidate))
|
| 45 |
+
except Exception:
|
| 46 |
+
raise HTTPException(status_code=400, detail="No se pudo leer el archivo fuente en el servidor")
|
| 47 |
+
else:
|
| 48 |
+
raise HTTPException(status_code=404, detail="Archivo fuente no encontrado en el servidor")
|
| 49 |
+
|
| 50 |
+
# If user_id + source_filename provided, check cache in MongoDB for existing generated image
|
| 51 |
+
if MONGODB_URI and user_id and source_filename:
|
| 52 |
+
try:
|
| 53 |
+
client = AsyncIOMotorClient(MONGODB_URI)
|
| 54 |
+
db = client["hyper_reality"]
|
| 55 |
+
col = db["generated"]
|
| 56 |
+
doc = await col.find_one({"user_id": user_id, "original_filename": source_filename, "texture": texture})
|
| 57 |
+
client.close()
|
| 58 |
+
if doc and doc.get("generated_filename"):
|
| 59 |
+
gen_file = GENERATED_DIR / doc["generated_filename"]
|
| 60 |
+
if gen_file.exists():
|
| 61 |
+
logger.info("/api/generate-image returning cached generated image: %s", str(gen_file))
|
| 62 |
+
data = gen_file.read_bytes()
|
| 63 |
+
b64 = base64.b64encode(data).decode("ascii")
|
| 64 |
+
return JSONResponse(content={"result_b64": b64, "message": "Returned cached generated image"})
|
| 65 |
+
except Exception:
|
| 66 |
+
logger.exception("Error checking generated cache in DB")
|
| 67 |
+
|
| 68 |
+
# Accept either a multipart file upload (`file`) or a base64 string in `image_b64`.
|
| 69 |
+
if contents is None and file is not None and getattr(file, "filename", None):
|
| 70 |
+
# multipart upload
|
| 71 |
+
if not file.content_type or not file.content_type.startswith("image/"):
|
| 72 |
+
raise HTTPException(status_code=400, detail="El archivo debe ser una imagen")
|
| 73 |
+
try:
|
| 74 |
+
contents = await file.read()
|
| 75 |
+
logger.info("/api/generate-image received file: %s (%s bytes)", file.filename, len(contents))
|
| 76 |
+
except Exception:
|
| 77 |
+
raise HTTPException(status_code=400, detail="No se pudo leer la imagen subida")
|
| 78 |
+
elif contents is None and image_b64:
|
| 79 |
+
# form field may include data URL prefix; strip if present
|
| 80 |
+
try:
|
| 81 |
+
if image_b64.startswith("data:") and "," in image_b64:
|
| 82 |
+
image_b64 = image_b64.split(",", 1)[1]
|
| 83 |
+
contents = base64.b64decode(image_b64)
|
| 84 |
+
logger.info("/api/generate-image received image_b64 (%s bytes)", len(contents))
|
| 85 |
+
except Exception:
|
| 86 |
+
raise HTTPException(status_code=400, detail="El campo image_b64 no contiene base64 válido")
|
| 87 |
+
else:
|
| 88 |
+
raise HTTPException(status_code=400, detail="No image provided. Send multipart 'file' or include 'image_b64' form field.")
|
| 89 |
|
| 90 |
try:
|
|
|
|
| 91 |
pil = Image.open(io.BytesIO(contents)).convert("RGB")
|
| 92 |
except Exception:
|
| 93 |
raise HTTPException(status_code=400, detail="No se pudo leer la imagen subida")
|
| 94 |
|
| 95 |
+
# Basic sanity checks: reject empty or trivially-small images before calling OpenAI
|
| 96 |
+
if not contents or len(contents) < 256:
|
| 97 |
+
raise HTTPException(status_code=400, detail="Imagen vacía o demasiado pequeña")
|
| 98 |
+
|
| 99 |
+
try:
|
| 100 |
+
w, h = pil.size
|
| 101 |
+
if w < 32 or h < 32:
|
| 102 |
+
raise HTTPException(status_code=400, detail="Imagen demasiado pequeña para procesar")
|
| 103 |
+
except HTTPException:
|
| 104 |
+
raise
|
| 105 |
+
except Exception:
|
| 106 |
+
raise HTTPException(status_code=400, detail="No se pudo determinar el tamaño de la imagen")
|
| 107 |
+
|
| 108 |
png_bytes, msg = generate_image_with_openai(api_key, pil, texture, preserve)
|
| 109 |
if png_bytes is None:
|
| 110 |
raise HTTPException(status_code=500, detail=msg)
|
| 111 |
|
| 112 |
+
# Persist generated image and record in DB (if available)
|
| 113 |
+
try:
|
| 114 |
+
gen_name = f"{uuid4().hex}.png"
|
| 115 |
+
gen_path = GENERATED_DIR / gen_name
|
| 116 |
+
gen_path.write_bytes(png_bytes)
|
| 117 |
+
logger.info("Saved generated image to %s", str(gen_path))
|
| 118 |
+
if MONGODB_URI and user_id:
|
| 119 |
+
try:
|
| 120 |
+
client = AsyncIOMotorClient(MONGODB_URI)
|
| 121 |
+
db = client["hyper_reality"]
|
| 122 |
+
col = db["generated"]
|
| 123 |
+
await col.replace_one(
|
| 124 |
+
{"user_id": user_id, "original_filename": source_filename or (getattr(file, 'filename', None) if file else None), "texture": texture},
|
| 125 |
+
{
|
| 126 |
+
"user_id": user_id,
|
| 127 |
+
"original_filename": source_filename or (getattr(file, 'filename', None) if file else None),
|
| 128 |
+
"texture": texture,
|
| 129 |
+
"generated_filename": gen_name,
|
| 130 |
+
"generated_url": f"/uploads/generated/{gen_name}",
|
| 131 |
+
"created_at": __import__('datetime').datetime.utcnow().isoformat() + 'Z',
|
| 132 |
+
},
|
| 133 |
+
upsert=True,
|
| 134 |
+
)
|
| 135 |
+
client.close()
|
| 136 |
+
except Exception:
|
| 137 |
+
logger.exception("Failed saving generated record to DB")
|
| 138 |
+
except Exception:
|
| 139 |
+
logger.exception("Failed saving generated image to disk")
|
| 140 |
+
|
| 141 |
b64 = __import__("base64").b64encode(png_bytes).decode("ascii")
|
| 142 |
return JSONResponse(content={"result_b64": b64, "message": msg})
|
backend/services/__pycache__/openai_service.cpython-312.pyc
CHANGED
|
Binary files a/backend/services/__pycache__/openai_service.cpython-312.pyc and b/backend/services/__pycache__/openai_service.cpython-312.pyc differ
|
|
|
backend/services/openai_service.py
CHANGED
|
@@ -6,6 +6,8 @@ from typing import Any, Tuple
|
|
| 6 |
|
| 7 |
import openai
|
| 8 |
from PIL import Image
|
|
|
|
|
|
|
| 9 |
|
| 10 |
from core.config import TEXTURE_DIR
|
| 11 |
|
|
@@ -74,7 +76,6 @@ def generate_image_with_openai(
|
|
| 74 |
pil_img: Image.Image,
|
| 75 |
texture: str,
|
| 76 |
preserve_percent: int = 0,
|
| 77 |
-
use_vision: bool = False,
|
| 78 |
) -> Tuple[bytes | None, str]:
|
| 79 |
"""
|
| 80 |
Genera/edita una imagen usando la API de OpenAI (gpt-image-1 edit).
|
|
@@ -85,38 +86,35 @@ def generate_image_with_openai(
|
|
| 85 |
return None, "OpenAI API key not provided"
|
| 86 |
|
| 87 |
texture_path, texture_display = _resolve_texture_path(texture)
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
else:
|
| 92 |
-
texture_desc = Path(texture_path).stem
|
| 93 |
|
| 94 |
-
#
|
| 95 |
acm_specs = ""
|
| 96 |
-
if
|
| 97 |
acm_specs = (
|
| 98 |
"ACM aluminum composite panel 4mm thick, 0.40mm aluminum layers, "
|
| 99 |
"panels sized 1.22m x 2.44m, clean precision-cut joints between panels, "
|
| 100 |
)
|
| 101 |
|
|
|
|
| 102 |
deck_specs = ""
|
| 103 |
-
if
|
| 104 |
deck_specs = (
|
| 105 |
"WPC deck boards (ash / \"ceniza\" color), plank dimensions 2.5 cm thick x 14 cm wide x 220 cm long, "
|
| 106 |
"installed as horizontal planks with 3-5 mm spacing and hidden fasteners, realistic wood grain, slight bevel on plank edges."
|
| 107 |
)
|
| 108 |
|
|
|
|
| 109 |
wpc_panel_specs = ""
|
| 110 |
-
if ("WPC" in
|
| 111 |
wpc_panel_specs = (
|
| 112 |
"WPC wall panels, each panel sized 0.16 m x 2.90 m (16 cm x 290 cm), realistic ash tone when appropriate, "
|
| 113 |
"installed with narrow vertical joints matching panel width and clean aligned seams."
|
| 114 |
)
|
| 115 |
|
| 116 |
-
#
|
| 117 |
-
tex_hex = _get_texture_hex(texture)
|
| 118 |
-
|
| 119 |
-
# Build prompt depending on type
|
| 120 |
if deck_specs:
|
| 121 |
prompt = (
|
| 122 |
f"Edit ONLY the HORIZONTAL floor/deck surfaces (decks, terraces, balcony floors, wooden walkways). "
|
|
@@ -142,6 +140,31 @@ def generate_image_with_openai(
|
|
| 142 |
f"Only change the wall surface material. Result must look like a photorealistic architectural photo."
|
| 143 |
)
|
| 144 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 145 |
if tex_hex:
|
| 146 |
prompt += f" Use the exact color sample {tex_hex} from the reference texture and match its hue, saturation and brightness precisely. Do not alter the color tone."
|
| 147 |
|
|
@@ -152,77 +175,30 @@ def generate_image_with_openai(
|
|
| 152 |
orig_size = pil_img_orig.size
|
| 153 |
square_img, padding, resized_dims = prepare_image_square(pil_img_orig)
|
| 154 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
buf = io.BytesIO()
|
| 156 |
-
|
| 157 |
buf.seek(0)
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
vision_prompt = (
|
| 169 |
-
"You are an architectural photographer. Describe exactly what is visible in this house photo: "
|
| 170 |
-
"number of floors, roof shape, main materials, prominent features (garage, balconies, large windows), "
|
| 171 |
-
"lighting conditions, and anything that affects how to apply a facade material. "
|
| 172 |
-
"Return a concise English description (max 200 words)."
|
| 173 |
-
)
|
| 174 |
-
|
| 175 |
-
vision_resp = client.chat.completions.create(
|
| 176 |
-
model="gpt-4o-mini",
|
| 177 |
-
messages=[{"role": "user", "content": f"data:image/jpeg;base64,{b64}\n\n{vision_prompt}"}],
|
| 178 |
-
max_tokens=300,
|
| 179 |
-
)
|
| 180 |
-
|
| 181 |
-
try:
|
| 182 |
-
house_desc = vision_resp.choices[0].message.content.strip()
|
| 183 |
-
except Exception:
|
| 184 |
-
house_desc = str(vision_resp)
|
| 185 |
-
except Exception:
|
| 186 |
-
house_desc = ""
|
| 187 |
-
|
| 188 |
-
if house_desc:
|
| 189 |
-
prompt = f"House description: {house_desc}. " + prompt
|
| 190 |
-
|
| 191 |
-
# If a texture file exists, try to attach it as a reference image to the API call.
|
| 192 |
-
tex_path, _ = _resolve_texture_path(texture)
|
| 193 |
-
try:
|
| 194 |
-
if tex_path:
|
| 195 |
-
with open(tex_path, "rb") as tf:
|
| 196 |
-
tex_buf = io.BytesIO(tf.read())
|
| 197 |
-
tex_buf.seek(0)
|
| 198 |
-
response = client.images.edit(
|
| 199 |
-
model="gpt-image-1",
|
| 200 |
-
image=("image.png", buf, "image/png"),
|
| 201 |
-
reference_image=(Path(tex_path).name, tex_buf, "image/png"),
|
| 202 |
-
prompt=prompt,
|
| 203 |
-
n=1,
|
| 204 |
-
size="1024x1024",
|
| 205 |
-
quality="medium",
|
| 206 |
-
)
|
| 207 |
-
else:
|
| 208 |
-
response = client.images.edit(
|
| 209 |
-
model="gpt-image-1",
|
| 210 |
-
image=("image.png", buf, "image/png"),
|
| 211 |
-
prompt=prompt,
|
| 212 |
-
n=1,
|
| 213 |
-
size="1024x1024",
|
| 214 |
-
quality="medium",
|
| 215 |
-
)
|
| 216 |
-
except Exception:
|
| 217 |
-
# Fallback: try without reference_image if SDK rejected the param
|
| 218 |
-
response = client.images.edit(
|
| 219 |
-
model="gpt-image-1",
|
| 220 |
-
image=("image.png", buf, "image/png"),
|
| 221 |
-
prompt=prompt,
|
| 222 |
-
n=1,
|
| 223 |
-
size="1024x1024",
|
| 224 |
-
quality="medium",
|
| 225 |
-
)
|
| 226 |
|
| 227 |
img_data = base64.b64decode(response.data[0].b64_json)
|
| 228 |
result_square = Image.open(io.BytesIO(img_data)).convert("RGBA")
|
|
@@ -231,20 +207,24 @@ def generate_image_with_openai(
|
|
| 231 |
result_cropped = result_square.crop((left, top, right, bottom))
|
| 232 |
result = result_cropped.resize(orig_size, Image.LANCZOS).convert("RGB")
|
| 233 |
|
| 234 |
-
#
|
| 235 |
-
|
| 236 |
-
preserve = max(0.0, min(1.0, float(preserve_percent) / 100.0))
|
| 237 |
-
except Exception:
|
| 238 |
-
preserve = 0.0
|
| 239 |
-
|
| 240 |
-
if preserve > 0:
|
| 241 |
-
pil_img_rgb = pil_img_orig.convert("RGB")
|
| 242 |
-
final = Image.blend(result, pil_img_rgb, preserve)
|
| 243 |
-
else:
|
| 244 |
-
final = result
|
| 245 |
|
| 246 |
out_buf = io.BytesIO()
|
| 247 |
final.save(out_buf, format="PNG")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 248 |
return out_buf.getvalue(), f"Generated with texture {texture_display if texture_display else texture_desc}"
|
| 249 |
|
| 250 |
except Exception as exc:
|
|
|
|
| 6 |
|
| 7 |
import openai
|
| 8 |
from PIL import Image
|
| 9 |
+
import time
|
| 10 |
+
from uuid import uuid4
|
| 11 |
|
| 12 |
from core.config import TEXTURE_DIR
|
| 13 |
|
|
|
|
| 76 |
pil_img: Image.Image,
|
| 77 |
texture: str,
|
| 78 |
preserve_percent: int = 0,
|
|
|
|
| 79 |
) -> Tuple[bytes | None, str]:
|
| 80 |
"""
|
| 81 |
Genera/edita una imagen usando la API de OpenAI (gpt-image-1 edit).
|
|
|
|
| 86 |
return None, "OpenAI API key not provided"
|
| 87 |
|
| 88 |
texture_path, texture_display = _resolve_texture_path(texture)
|
| 89 |
+
# derive texture_stem for rules
|
| 90 |
+
texture_stem = Path(texture_path).stem if texture_path else (Path(texture).stem if texture and isinstance(texture, str) else "")
|
| 91 |
+
texture_desc = TEXTURE_DESCRIPTIONS.get(texture_stem, texture_display if texture_display else texture)
|
|
|
|
|
|
|
| 92 |
|
| 93 |
+
# Specs técnicas ACM
|
| 94 |
acm_specs = ""
|
| 95 |
+
if texture_stem and texture_stem.upper().startswith("ACM"):
|
| 96 |
acm_specs = (
|
| 97 |
"ACM aluminum composite panel 4mm thick, 0.40mm aluminum layers, "
|
| 98 |
"panels sized 1.22m x 2.44m, clean precision-cut joints between panels, "
|
| 99 |
)
|
| 100 |
|
| 101 |
+
# Enriquecimientos específicos para DECK (pisos / decking)
|
| 102 |
deck_specs = ""
|
| 103 |
+
if texture_stem.startswith("DECK") or ("DECK" in texture_stem):
|
| 104 |
deck_specs = (
|
| 105 |
"WPC deck boards (ash / \"ceniza\" color), plank dimensions 2.5 cm thick x 14 cm wide x 220 cm long, "
|
| 106 |
"installed as horizontal planks with 3-5 mm spacing and hidden fasteners, realistic wood grain, slight bevel on plank edges."
|
| 107 |
)
|
| 108 |
|
| 109 |
+
# Especificación de PANEL WPC (revestimiento exterior/interior)
|
| 110 |
wpc_panel_specs = ""
|
| 111 |
+
if ("WPC" in texture_stem) and ("DECK" not in texture_stem):
|
| 112 |
wpc_panel_specs = (
|
| 113 |
"WPC wall panels, each panel sized 0.16 m x 2.90 m (16 cm x 290 cm), realistic ash tone when appropriate, "
|
| 114 |
"installed with narrow vertical joints matching panel width and clean aligned seams."
|
| 115 |
)
|
| 116 |
|
| 117 |
+
# Build prompt variants
|
|
|
|
|
|
|
|
|
|
| 118 |
if deck_specs:
|
| 119 |
prompt = (
|
| 120 |
f"Edit ONLY the HORIZONTAL floor/deck surfaces (decks, terraces, balcony floors, wooden walkways). "
|
|
|
|
| 140 |
f"Only change the wall surface material. Result must look like a photorealistic architectural photo."
|
| 141 |
)
|
| 142 |
|
| 143 |
+
# Añadir instrucciones de preservación de escala/dimensiones
|
| 144 |
+
size_text = ""
|
| 145 |
+
if deck_specs:
|
| 146 |
+
size_text = (
|
| 147 |
+
" Respect the real-world plank dimensions: 2.5 cm thick x 14 cm wide x 220 cm long. "
|
| 148 |
+
"Scale the texture so plank width and length match these measurements proportionally in the photo, including spacing."
|
| 149 |
+
)
|
| 150 |
+
elif wpc_panel_specs:
|
| 151 |
+
size_text = (
|
| 152 |
+
" Respect the real-world panel dimensions: 0.16 m x 2.90 m per panel. "
|
| 153 |
+
"Scale the texture so vertical panel widths and joint spacing correspond to these real dimensions."
|
| 154 |
+
)
|
| 155 |
+
|
| 156 |
+
constraint_text = (
|
| 157 |
+
" CRITICAL: Do NOT change geometry, add or remove architectural elements, alter windows, doors, roofs, "
|
| 158 |
+
"gardens, people, vehicles, or sky. Do NOT modify shadows, reflections, perspective, or lighting. "
|
| 159 |
+
"Only replace the surface material of the targeted areas. Preserve all original non-target textures, finishes, and details. "
|
| 160 |
+
"Match the scale, grain and color of the selected texture; do not stylize or apply artistic filters."
|
| 161 |
+
) + size_text
|
| 162 |
+
|
| 163 |
+
texture_ref_text = f" Use the selected texture sample as the reference for color, pattern and grain: {texture_desc}."
|
| 164 |
+
prompt = prompt + constraint_text + texture_ref_text
|
| 165 |
+
|
| 166 |
+
# If we have a texture file, attempt to compute its representative color and ask model to match it
|
| 167 |
+
tex_hex = _get_texture_hex(texture)
|
| 168 |
if tex_hex:
|
| 169 |
prompt += f" Use the exact color sample {tex_hex} from the reference texture and match its hue, saturation and brightness precisely. Do not alter the color tone."
|
| 170 |
|
|
|
|
| 175 |
orig_size = pil_img_orig.size
|
| 176 |
square_img, padding, resized_dims = prepare_image_square(pil_img_orig)
|
| 177 |
|
| 178 |
+
# Ensure we send an RGB image with white background (match imagneConaI/app.py behavior)
|
| 179 |
+
if square_img.mode != "RGB":
|
| 180 |
+
bg = Image.new("RGB", square_img.size, (255, 255, 255))
|
| 181 |
+
if square_img.mode == "RGBA":
|
| 182 |
+
bg.paste(square_img, (0, 0), square_img)
|
| 183 |
+
else:
|
| 184 |
+
bg.paste(square_img.convert("RGB"))
|
| 185 |
+
square_for_api = bg
|
| 186 |
+
else:
|
| 187 |
+
square_for_api = square_img
|
| 188 |
+
|
| 189 |
buf = io.BytesIO()
|
| 190 |
+
square_for_api.save(buf, format="PNG")
|
| 191 |
buf.seek(0)
|
| 192 |
+
img_input_bytes = buf.getvalue()
|
| 193 |
+
|
| 194 |
+
# Call the API with the same parameters as imagneConaI/app.py (no reference_image param)
|
| 195 |
+
response = client.images.edit(
|
| 196 |
+
model="gpt-image-1",
|
| 197 |
+
image=("image.png", io.BytesIO(img_input_bytes), "image/png"),
|
| 198 |
+
prompt=prompt,
|
| 199 |
+
n=1,
|
| 200 |
+
size="1024x1024",
|
| 201 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
|
| 203 |
img_data = base64.b64decode(response.data[0].b64_json)
|
| 204 |
result_square = Image.open(io.BytesIO(img_data)).convert("RGBA")
|
|
|
|
| 207 |
result_cropped = result_square.crop((left, top, right, bottom))
|
| 208 |
result = result_cropped.resize(orig_size, Image.LANCZOS).convert("RGB")
|
| 209 |
|
| 210 |
+
# Do not blend with original image: return the generated result as-is
|
| 211 |
+
final = result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 212 |
|
| 213 |
out_buf = io.BytesIO()
|
| 214 |
final.save(out_buf, format="PNG")
|
| 215 |
+
|
| 216 |
+
# Debug: save prompt, input and response when requested
|
| 217 |
+
try:
|
| 218 |
+
if os.getenv("OPENAI_SAVE_RESPONSES", "0") == "1":
|
| 219 |
+
dbg_dir = Path.cwd() / "backend_outputs" / "openai_debug"
|
| 220 |
+
dbg_dir.mkdir(parents=True, exist_ok=True)
|
| 221 |
+
prefix = f"openai_{int(time.time())}_{uuid4().hex[:6]}"
|
| 222 |
+
(dbg_dir / f"{prefix}_prompt.txt").write_text(prompt, encoding="utf8")
|
| 223 |
+
(dbg_dir / f"{prefix}_input.png").write_bytes(img_input_bytes)
|
| 224 |
+
(dbg_dir / f"{prefix}_resp.png").write_bytes(out_buf.getvalue())
|
| 225 |
+
except Exception:
|
| 226 |
+
pass
|
| 227 |
+
|
| 228 |
return out_buf.getvalue(), f"Generated with texture {texture_display if texture_display else texture_desc}"
|
| 229 |
|
| 230 |
except Exception as exc:
|
backend/uploads/0489e41ca42c4f62972f9df4048f4fee.jpg
ADDED
|
backend/uploads/0d38e64424a44bfea0d2cd60b6ab7ca7.jpg
ADDED
|
backend/uploads/44551e85423f44e28220e796e8aad972.jpg
ADDED
|
backend/uploads/6aae686070084421be72844fcab3432c.jpg
ADDED
|
backend/uploads/91484306cbd94cc187cf2666993e17fd.jpg
ADDED
|
backend/uploads/977ec30d99304e2a95328c448b8e71f7.jpg
ADDED
|
backend/uploads/99256e3e599c4ed0ab1cfb9ed3823137.jpg
ADDED
|
backend/uploads/b60b62ea9b67460d9f192fc7e46f0017.jpg
ADDED
|
backend/uploads/db11756ac9d04460a06785f066342331.jpg
ADDED
|
backend/uploads/f652de6149aa4fd6a775c770e5736367.jpg
ADDED
|
backend/uploads/f8a0db84234c426e9252ee65e958f77a.jpg
ADDED
|
backend/uploads/generated/032d76c129a442cebeac3323bc4fc080.png
ADDED
|
Git LFS Details
|
backend/uploads/generated/08a1798e9521455a902edda85dc029cc.png
ADDED
|
Git LFS Details
|
backend/uploads/generated/1bc4caa711694fb8acca6b23159f754f.png
ADDED
|
Git LFS Details
|
backend/uploads/generated/231900b690ad4adb9883a3d600716a7d.png
ADDED
|
Git LFS Details
|
backend/uploads/generated/2a5b913b68a243379027cd01b187b4cd.png
ADDED
|
Git LFS Details
|
backend/uploads/generated/2d6e02255c3a4f00804ace65c49f19aa.png
ADDED
|
Git LFS Details
|
backend/uploads/generated/5b6f11b554f74c5486ce33e390f8c75d.png
ADDED
|
Git LFS Details
|
backend/uploads/generated/836b20819d49430a9fc94c02e8e07885.png
ADDED
|
Git LFS Details
|
backend/uploads/generated/d664c83e3b614760834cdaad28769340.png
ADDED
|
Git LFS Details
|
backend/uploads/generated/dbd083972cf5430998885a9f7c36ac0a.png
ADDED
|
Git LFS Details
|
frontend/dist/assets/index-CenEQfA2.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
*,:before,:after,::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content:""}html,:host{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{line-height:inherit;margin:0}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (width>=640px){.container{max-width:640px}}@media (width>=768px){.container{max-width:768px}}@media (width>=1024px){.container{max-width:1024px}}@media (width>=1280px){.container{max-width:1280px}}@media (width>=1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-x-0{left:0;right:0}.-bottom-1{bottom:-.25rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-10{bottom:2.5rem}.bottom-12{bottom:3rem}.left-0{left:0}.left-1\/2{left:50%}.left-3{left:.75rem}.right-0{right:0}.right-2{right:.5rem}.right-3{right:.75rem}.top-0{top:0}.top-1\/2{top:50%}.top-12{top:3rem}.top-14{top:3.5rem}.top-2{top:.5rem}.z-10{z-index:10}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.my-5{margin-top:1.25rem;margin-bottom:1.25rem}.mb-1{margin-bottom:.25rem}.mb-10{margin-bottom:2.5rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-auto{margin-left:auto}.mt-1{margin-top:.25rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-8{margin-top:2rem}.mt-\[3px\]{margin-top:3px}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.aspect-\[4\/3\]{aspect-ratio:4/3}.aspect-square{aspect-ratio:1}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-24{height:6rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-32{height:8rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-\[1px\]{height:1px}.h-full{height:100%}.h-screen{height:100vh}.max-h-full{max-height:100%}.min-h-0{min-height:0}.min-h-\[220px\]{min-height:220px}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-14{width:3.5rem}.w-2{width:.5rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-\[80\%\]{width:80%}.w-fit{width:fit-content}.w-full{width:100%}.min-w-0{min-width:0}.max-w-7xl{max-width:80rem}.max-w-\[260px\]{max-width:260px}.max-w-full{max-width:100%}.max-w-xs{max-width:20rem}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:-50%;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-45{--tw-rotate:45deg;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}}.animate-bounce{animation:1s infinite bounce}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:2s cubic-bezier(.4,0,.6,1) infinite pulse}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:1s linear infinite spin}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.whitespace-nowrap{white-space:nowrap}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.rounded-b-md{border-bottom-right-radius:.375rem;border-bottom-left-radius:.375rem}.rounded-t-md{border-top-left-radius:.375rem;border-top-right-radius:.375rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-\[\#0047AB\]{--tw-border-opacity:1;border-color:rgb(0 71 171/var(--tw-border-opacity,1))}.border-\[\#0047AB\]\/10{border-color:#0047ab1a}.border-\[\#0047AB\]\/20{border-color:#0047ab33}.border-\[\#dbe7ff\]{--tw-border-opacity:1;border-color:rgb(219 231 255/var(--tw-border-opacity,1))}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity,1))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1))}.border-transparent{border-color:#0000}.bg-\[\#0047AB\]{--tw-bg-opacity:1;background-color:rgb(0 71 171/var(--tw-bg-opacity,1))}.bg-\[\#0047AB\]\/20{background-color:#0047ab33}.bg-\[\#0047AB\]\/80{background-color:#0047abcc}.bg-\[\#333333\]{--tw-bg-opacity:1;background-color:rgb(51 51 51/var(--tw-bg-opacity,1))}.bg-\[\#eaf1ff\]{--tw-bg-opacity:1;background-color:rgb(234 241 255/var(--tw-bg-opacity,1))}.bg-\[\#edf4ff\]{--tw-bg-opacity:1;background-color:rgb(237 244 255/var(--tw-bg-opacity,1))}.bg-\[\#f4f8ff\]{--tw-bg-opacity:1;background-color:rgb(244 248 255/var(--tw-bg-opacity,1))}.bg-black\/0{background-color:#0000}.bg-black\/40{background-color:#0006}.bg-black\/50{background-color:#00000080}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.bg-gray-950{--tw-bg-opacity:1;background-color:rgb(3 7 18/var(--tw-bg-opacity,1))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.bg-transparent{background-color:#0000}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-white\/80{background-color:#fffc}.bg-yellow-400{--tw-bg-opacity:1;background-color:rgb(250 204 21/var(--tw-bg-opacity,1))}.bg-zinc-400{--tw-bg-opacity:1;background-color:rgb(161 161 170/var(--tw-bg-opacity,1))}.bg-gradient-to-t{background-image:linear-gradient(to top, var(--tw-gradient-stops))}.from-black\/60{--tw-gradient-from:#0009 var(--tw-gradient-from-position);--tw-gradient-to:#0000 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.via-transparent{--tw-gradient-to:#0000 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), transparent var(--tw-gradient-via-position), var(--tw-gradient-to)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pb-2{padding-bottom:.5rem}.pb-4{padding-bottom:1rem}.pl-11{padding-left:2.75rem}.pr-10{padding-right:2.5rem}.pr-12{padding-right:3rem}.text-left{text-align:left}.text-center{text-align:center}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.text-\[17px\]{font-size:17px}.text-\[9px\]{font-size:9px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-light{font-weight:300}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-tight{line-height:1.25}.tracking-tight{letter-spacing:-.025em}.tracking-tighter{letter-spacing:-.05em}.tracking-widest{letter-spacing:.1em}.text-\[\#0047AB\]{--tw-text-opacity:1;color:rgb(0 71 171/var(--tw-text-opacity,1))}.text-\[\#333333\],.text-\[\#333\]{--tw-text-opacity:1;color:rgb(51 51 51/var(--tw-text-opacity,1))}.text-\[\#4a7fd4\]{--tw-text-opacity:1;color:rgb(74 127 212/var(--tw-text-opacity,1))}.text-\[\#555\]{--tw-text-opacity:1;color:rgb(85 85 85/var(--tw-text-opacity,1))}.text-\[\#707070\]{--tw-text-opacity:1;color:rgb(112 112 112/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-slate-800{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/80{color:#fffc}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-30{opacity:.3}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow:0 25px 50px -12px #00000040;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-\[\#0047AB\]\/20{--tw-shadow-color:#0047ab33;--tw-shadow:var(--tw-shadow-colored)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow-sm{--tw-drop-shadow:drop-shadow(0 1px 1px #0000000d);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter,backdrop-filter;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-all{transition-property:all;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-opacity{transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-transform{transition-property:transform;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.\[animation-delay\:-0\.15s\]{animation-delay:-.15s}.\[animation-delay\:-0\.3s\]{animation-delay:-.3s}:root{--brand-blue:#0047ab;--brand-black:#333;--brand-gray:#707070;--brand-surface:#fff;--brand-light:#f4f8ff;--brand-border:#dbe7ff;--brand-contrast:#25d366;color:var(--brand-black);background:var(--brand-light);font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:16px}*,:before,:after{box-sizing:border-box}html{overscroll-behavior:none;height:100%}body{color:#111827;overscroll-behavior:none;background:#f8fafc;height:100%;min-height:100dvh;margin:0}#root{flex-direction:column;height:100%;min-height:100dvh;display:flex}a{color:inherit;text-decoration:none}img{max-width:100%;display:block}h1,h2,h3,p{margin:0}ul{margin:0;padding:0;list-style:none}.last\:border-0:last-child{border-width:0}.hover\:border-\[\#0047AB\]:hover{--tw-border-opacity:1;border-color:rgb(0 71 171/var(--tw-border-opacity,1))}.hover\:border-\[\#0047AB\]\/40:hover{border-color:#0047ab66}.hover\:border-\[\#0047AB\]\/50:hover{border-color:#0047ab80}.hover\:bg-\[\#003a94\]:hover{--tw-bg-opacity:1;background-color:rgb(0 58 148/var(--tw-bg-opacity,1))}.hover\:bg-\[\#eaf1ff\]:hover{--tw-bg-opacity:1;background-color:rgb(234 241 255/var(--tw-bg-opacity,1))}.hover\:bg-\[\#eef4ff\]:hover{--tw-bg-opacity:1;background-color:rgb(238 244 255/var(--tw-bg-opacity,1))}.hover\:bg-\[\#f4f8ff\]:hover{--tw-bg-opacity:1;background-color:rgb(244 248 255/var(--tw-bg-opacity,1))}.hover\:bg-black:hover{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.hover\:bg-red-500:hover{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.hover\:text-\[\#002c75\]:hover{--tw-text-opacity:1;color:rgb(0 44 117/var(--tw-text-opacity,1))}.hover\:text-gray-600:hover{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.focus\:outline-none:focus{outline-offset:2px;outline:2px solid #0000}.disabled\:opacity-60:disabled{opacity:.6}.group:hover .group-hover\:translate-x-1{--tw-translate-x:.25rem;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:border-\[\#0047AB\]{--tw-border-opacity:1;border-color:rgb(0 71 171/var(--tw-border-opacity,1))}.group:hover .group-hover\:bg-black\/10{background-color:#0000001a}.group:hover .group-hover\:opacity-100{opacity:1}@media (width>=640px){.sm\:mb-14{margin-bottom:3.5rem}.sm\:mb-16{margin-bottom:4rem}.sm\:mb-4{margin-bottom:1rem}.sm\:mb-6{margin-bottom:1.5rem}.sm\:mb-8{margin-bottom:2rem}.sm\:mt-4{margin-top:1rem}.sm\:aspect-\[4\/3\]{aspect-ratio:4/3}.sm\:h-16{height:4rem}.sm\:h-32{height:8rem}.sm\:h-6{height:1.5rem}.sm\:h-8{height:2rem}.sm\:min-h-0{min-height:0}.sm\:w-16{width:4rem}.sm\:w-32{width:8rem}.sm\:w-6{width:1.5rem}.sm\:w-72{width:18rem}.sm\:w-8{width:2rem}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:gap-6{gap:1.5rem}.sm\:space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-4{padding-top:1rem;padding-bottom:1rem}.sm\:py-8{padding-top:2rem;padding-bottom:2rem}.sm\:text-2xl{font-size:1.5rem;line-height:2rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}.sm\:text-base{font-size:1rem;line-height:1.5rem}.sm\:text-lg{font-size:1.125rem;line-height:1.75rem}.sm\:text-xl{font-size:1.25rem;line-height:1.75rem}}@media (width>=768px){.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (width>=1024px){.lg\:bottom-16{bottom:4rem}.lg\:top-16{top:4rem}.lg\:top-20{top:5rem}.lg\:mb-10{margin-bottom:2.5rem}.lg\:mb-20{margin-bottom:5rem}.lg\:mb-8{margin-bottom:2rem}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:gap-12{gap:3rem}.lg\:rounded-lg{border-radius:.5rem}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:text-4xl{font-size:2.25rem;line-height:2.5rem}}:root{color:var(--brand-black);background:var(--brand-light);font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;line-height:1.5}*{box-sizing:border-box}html,body,#root{min-height:100%}body{background:var(--brand-light);color:var(--brand-black);margin:0}button,input,select,textarea{font:inherit}button{cursor:pointer}.app-shell{max-width:1200px;margin:0 auto;padding:24px}.topbar{background:var(--brand-surface);border:1px solid var(--brand-border);border-radius:18px;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:16px;padding:22px 24px;display:flex}.topbar h1{margin:0;font-size:clamp(1.9rem,2.5vw,2.6rem)}.topbar p{color:var(--brand-gray);margin:6px 0 0}.topbar-nav{flex-wrap:wrap;gap:10px;display:flex}.topbar-nav a{background:var(--brand-surface);color:var(--brand-black);border:1px solid #0000;border-radius:14px;justify-content:center;align-items:center;padding:10px 14px;text-decoration:none;transition:background .2s,border-color .2s;display:inline-flex}.topbar-nav a:hover{background:#fff;border-color:#d1d5db}.content{grid-template-columns:1.2fr 1.8fr;gap:24px;margin-top:24px;display:grid}.route-index,.panel,.viewer-panel,.bridge-panel,.room-setup-dropzone,.room-setup-card,.room-setup-preview{background:var(--brand-surface);border:1px solid var(--brand-border);border-radius:20px}.route-index,.panel,.viewer-panel,.bridge-panel,.room-setup-card{padding:22px}.route-index h2,.panel h2,.viewer-panel h2,.room-setup-copy h1,.room-setup-bottom h2{margin:0 0 16px}.route-index p,.room-setup-features li,.room-setup-drop-content p,.room-setup-drop-content small,.room-setup-card h3,.topbar p,.error-box,.empty-state{color:#475569}.route-index ul,.room-setup-features,.room-setup-filters,.room-setup-grid{margin:0;padding:0;list-style:none}.route-index ul{gap:12px;display:grid}.form-row{gap:14px;margin-bottom:20px;display:grid}label{color:var(--brand-black);font-size:.95rem}input,select,textarea{color:#111827;background:#fff;border:1px solid #d1d5db;border-radius:14px;width:100%;padding:14px 16px}input:focus,select:focus,textarea:focus{outline:2px solid var(--brand-blue);outline-offset:2px}.button,.button-primary,.button-secondary{border:1px solid #0000;border-radius:16px;justify-content:center;align-items:center;gap:10px;padding:14px 18px;font-weight:700;transition:all .2s;display:inline-flex}.button{background:var(--brand-black);color:var(--brand-surface)}.button:hover{opacity:.95}.button.secondary,.button-secondary{background:var(--brand-surface);color:var(--brand-black);border-color:var(--brand-border)}.error-box{color:#991b1b;background:#fef2f2;border:1px solid #fecaca;border-radius:16px;margin-top:16px;padding:16px}.empty-state{border:1px dashed #d1d5db;border-radius:18px;place-content:center;min-height:220px;display:grid}.room-setup{background:var(--brand-light)}.room-setup-inner{max-width:1200px;margin:0 auto;padding:32px 24px}.room-setup-header{justify-content:flex-end;margin-bottom:24px;display:flex}.room-setup-close{color:var(--brand-black);cursor:pointer;background:0 0;border:none;border-radius:999px;padding:10px}.room-setup-close:hover{background:var(--brand-border)}.room-setup-top{grid-template-columns:1.1fr .9fr;gap:24px;margin-bottom:40px;display:grid}.room-setup-copy h1{color:#111827;margin:0 0 24px;font-size:clamp(2rem,2.5vw,3rem)}.room-setup-features{gap:16px;display:grid}.room-setup-features li{color:#475569;align-items:center;gap:12px;display:flex}.room-setup-actions{gap:16px;display:grid}.button-primary{color:#fff;background:#111827}.button-primary:hover{opacity:.95}.button-secondary{color:#334155;background:#fff;border-color:#d1d5db}.button-secondary:hover{background:#f3f4f6}.button-icon-border{border:1px solid #d1d5db;border-radius:10px;justify-content:center;align-items:center;width:30px;height:30px;display:inline-flex}.room-setup-dropzone{border:1px dashed #d1d5db;border-radius:28px;justify-content:center;align-items:center;min-height:420px;padding:24px;transition:all .2s;display:flex;position:relative}.room-setup-dropzone.dragging{background:#f3f4f6}.room-setup-file-input{opacity:0;cursor:pointer;width:100%;height:100%;position:absolute;inset:0}.room-setup-drop-content{text-align:center}.room-setup-drop-icon{color:#64748b;background:#e2e8f0;border-radius:999px;justify-content:center;align-items:center;width:72px;height:72px;margin-bottom:18px;display:inline-flex}.room-setup-drop-icon.active{color:#1e293b;background:#dbeafe}.room-setup-drop-content h3{margin:0 0 8px;font-size:1.2rem}.room-setup-drop-content p,.room-setup-drop-content small{color:#64748b;margin:0}.room-setup-preview{width:100%;height:100%;position:relative}.room-setup-preview img{-o-object-fit:cover;object-fit:cover;width:100%;height:100%}.room-setup-preview-overlay{opacity:0;background:#ffffffd9;justify-content:center;align-items:center;transition:opacity .2s;display:flex;position:absolute;inset:0}.room-setup-preview:hover .room-setup-preview-overlay{opacity:1}.button-delete{color:#111827;background:#fff;border:1px solid #d1d5db;border-radius:14px;padding:12px 16px;font-weight:600}.room-setup-bottom h2{margin:0 0 24px}.room-setup-filters{flex-wrap:wrap;gap:10px;margin-bottom:24px;display:flex}.room-setup-filter{color:#334155;cursor:pointer;background:#fff;border:1px solid #d1d5db;border-radius:16px;padding:10px 16px;transition:all .2s}.room-setup-filter.active{background:#f3f4f6}.room-setup-grid{grid-template-columns:repeat(1,minmax(0,1fr));gap:20px;display:grid}.room-setup-card{background:#fff;border-radius:24px;overflow:hidden;box-shadow:0 8px 20px #0f172a0f}.room-setup-card-image{aspect-ratio:4/3;position:relative;overflow:hidden}.room-setup-card-image img{-o-object-fit:cover;object-fit:cover;width:100%;height:100%;transition:transform .4s}.room-setup-card:hover .room-setup-card-image img{transform:scale(1.04)}.room-setup-card h3{color:#334155;margin:16px;font-size:1rem}@media (width<=960px){.room-setup-top{grid-template-columns:1fr}.room-setup-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width<=640px){.room-setup-inner{padding:20px 16px}.room-setup-grid{grid-template-columns:1fr}}.app-version-badge{color:#475569;text-align:right;z-index:1000;background:#fffffff2;border:1px solid #e5e7eb;border-radius:12px 0 0;padding:6px 10px;font-size:.78rem;position:fixed;bottom:0;right:0;box-shadow:0 8px 20px #0f172a14}.app-version-badge:hover{opacity:1}.app-version-badge span{color:#111827;font-weight:700;display:block}.app-version-badge small{color:#6b7280;margin-top:1px;display:block}@media (width<=640px){.app-version-badge{padding:5px 8px;font-size:.72rem;bottom:6px;right:6px}.app-version-badge small{margin-top:.5px}}@media (width<=900px){.content{grid-template-columns:1fr}}
|
frontend/dist/assets/index-DE9xapIa.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
frontend/dist/index.html
CHANGED
|
@@ -4,7 +4,10 @@
|
|
| 4 |
<meta charset="UTF-8" />
|
| 5 |
|
| 6 |
<!-- Viewport: viewport-fit=cover extiende hasta los bordes en dispositivos con notch -->
|
| 7 |
-
<meta
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
<!-- PWA -->
|
| 10 |
<link rel="manifest" href="/manifest.json" />
|
|
@@ -12,7 +15,11 @@
|
|
| 12 |
|
| 13 |
<!-- iOS PWA: fullscreen al instalarse desde Safari -->
|
| 14 |
<meta name="apple-mobile-web-app-capable" content="yes" />
|
| 15 |
-
<meta name="
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
<meta name="apple-mobile-web-app-title" content="Hyper Reality" />
|
| 17 |
<link rel="apple-touch-icon" href="/favicon.svg" />
|
| 18 |
|
|
@@ -20,8 +27,8 @@
|
|
| 20 |
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
| 21 |
|
| 22 |
<title>Hyper Reality Visualizer</title>
|
| 23 |
-
<script type="module" crossorigin src="/assets/index-
|
| 24 |
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
| 25 |
</head>
|
| 26 |
<body>
|
| 27 |
<div id="root"></div>
|
|
|
|
| 4 |
<meta charset="UTF-8" />
|
| 5 |
|
| 6 |
<!-- Viewport: viewport-fit=cover extiende hasta los bordes en dispositivos con notch -->
|
| 7 |
+
<meta
|
| 8 |
+
name="viewport"
|
| 9 |
+
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
|
| 10 |
+
/>
|
| 11 |
|
| 12 |
<!-- PWA -->
|
| 13 |
<link rel="manifest" href="/manifest.json" />
|
|
|
|
| 15 |
|
| 16 |
<!-- iOS PWA: fullscreen al instalarse desde Safari -->
|
| 17 |
<meta name="apple-mobile-web-app-capable" content="yes" />
|
| 18 |
+
<meta name="mobile-web-app-capable" content="yes" />
|
| 19 |
+
<meta
|
| 20 |
+
name="apple-mobile-web-app-status-bar-style"
|
| 21 |
+
content="black-translucent"
|
| 22 |
+
/>
|
| 23 |
<meta name="apple-mobile-web-app-title" content="Hyper Reality" />
|
| 24 |
<link rel="apple-touch-icon" href="/favicon.svg" />
|
| 25 |
|
|
|
|
| 27 |
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
| 28 |
|
| 29 |
<title>Hyper Reality Visualizer</title>
|
| 30 |
+
<script type="module" crossorigin src="/assets/index-DE9xapIa.js"></script>
|
| 31 |
+
<link rel="stylesheet" crossorigin href="/assets/index-CenEQfA2.css">
|
| 32 |
</head>
|
| 33 |
<body>
|
| 34 |
<div id="root"></div>
|
frontend/index.html
CHANGED
|
@@ -4,7 +4,10 @@
|
|
| 4 |
<meta charset="UTF-8" />
|
| 5 |
|
| 6 |
<!-- Viewport: viewport-fit=cover extiende hasta los bordes en dispositivos con notch -->
|
| 7 |
-
<meta
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
<!-- PWA -->
|
| 10 |
<link rel="manifest" href="/manifest.json" />
|
|
@@ -12,7 +15,11 @@
|
|
| 12 |
|
| 13 |
<!-- iOS PWA: fullscreen al instalarse desde Safari -->
|
| 14 |
<meta name="apple-mobile-web-app-capable" content="yes" />
|
| 15 |
-
<meta name="
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
<meta name="apple-mobile-web-app-title" content="Hyper Reality" />
|
| 17 |
<link rel="apple-touch-icon" href="/favicon.svg" />
|
| 18 |
|
|
|
|
| 4 |
<meta charset="UTF-8" />
|
| 5 |
|
| 6 |
<!-- Viewport: viewport-fit=cover extiende hasta los bordes en dispositivos con notch -->
|
| 7 |
+
<meta
|
| 8 |
+
name="viewport"
|
| 9 |
+
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
|
| 10 |
+
/>
|
| 11 |
|
| 12 |
<!-- PWA -->
|
| 13 |
<link rel="manifest" href="/manifest.json" />
|
|
|
|
| 15 |
|
| 16 |
<!-- iOS PWA: fullscreen al instalarse desde Safari -->
|
| 17 |
<meta name="apple-mobile-web-app-capable" content="yes" />
|
| 18 |
+
<meta name="mobile-web-app-capable" content="yes" />
|
| 19 |
+
<meta
|
| 20 |
+
name="apple-mobile-web-app-status-bar-style"
|
| 21 |
+
content="black-translucent"
|
| 22 |
+
/>
|
| 23 |
<meta name="apple-mobile-web-app-title" content="Hyper Reality" />
|
| 24 |
<link rel="apple-touch-icon" href="/favicon.svg" />
|
| 25 |
|
frontend/src/features/roomSetup/RoomSetup.tsx
CHANGED
|
@@ -16,7 +16,10 @@ import useAppStore from "../../store/useAppStore";
|
|
| 16 |
import { useHistoryStore, type HistoryItem } from "../../store/useAppStore";
|
| 17 |
import { useActiveSessions } from "../../hooks/useActiveSessions";
|
| 18 |
import { API_BASE } from "../../api/client";
|
| 19 |
-
import {
|
|
|
|
|
|
|
|
|
|
| 20 |
import { useCallback } from "react";
|
| 21 |
|
| 22 |
export default function RoomSetup() {
|
|
@@ -222,8 +225,10 @@ export default function RoomSetup() {
|
|
| 222 |
style={{ scrollbarWidth: "thin" }}
|
| 223 |
>
|
| 224 |
{sessionHistory.map((item: HistoryItem) => (
|
| 225 |
-
<
|
| 226 |
key={item.filename}
|
|
|
|
|
|
|
| 227 |
onClick={() =>
|
| 228 |
navigate("/visualizer", {
|
| 229 |
state: {
|
|
@@ -233,6 +238,17 @@ export default function RoomSetup() {
|
|
| 233 |
},
|
| 234 |
})
|
| 235 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 236 |
className={`flex-shrink-0 group relative rounded-2xl overflow-hidden border-2 transition-all duration-200 ${
|
| 237 |
segmentFilename === item.filename
|
| 238 |
? "border-[#0047AB] shadow-lg shadow-[#0047AB]/20"
|
|
@@ -277,7 +293,7 @@ export default function RoomSetup() {
|
|
| 277 |
Continuar <ArrowRight className="w-3.5 h-3.5" />
|
| 278 |
</span>
|
| 279 |
</div>
|
| 280 |
-
</
|
| 281 |
))}
|
| 282 |
</div>
|
| 283 |
</section>
|
|
|
|
| 16 |
import { useHistoryStore, type HistoryItem } from "../../store/useAppStore";
|
| 17 |
import { useActiveSessions } from "../../hooks/useActiveSessions";
|
| 18 |
import { API_BASE } from "../../api/client";
|
| 19 |
+
import {
|
| 20 |
+
useLoadSessionHistory,
|
| 21 |
+
deleteSessionFromBackend,
|
| 22 |
+
} from "../../hooks/useSessionSync";
|
| 23 |
import { useCallback } from "react";
|
| 24 |
|
| 25 |
export default function RoomSetup() {
|
|
|
|
| 225 |
style={{ scrollbarWidth: "thin" }}
|
| 226 |
>
|
| 227 |
{sessionHistory.map((item: HistoryItem) => (
|
| 228 |
+
<div
|
| 229 |
key={item.filename}
|
| 230 |
+
role="button"
|
| 231 |
+
tabIndex={0}
|
| 232 |
onClick={() =>
|
| 233 |
navigate("/visualizer", {
|
| 234 |
state: {
|
|
|
|
| 238 |
},
|
| 239 |
})
|
| 240 |
}
|
| 241 |
+
onKeyDown={(e) => {
|
| 242 |
+
if (e.key === "Enter" || e.key === " ") {
|
| 243 |
+
navigate("/visualizer", {
|
| 244 |
+
state: {
|
| 245 |
+
previewImage: item.previewUrl,
|
| 246 |
+
filename: item.filename,
|
| 247 |
+
maskCount: item.maskCount,
|
| 248 |
+
},
|
| 249 |
+
});
|
| 250 |
+
}
|
| 251 |
+
}}
|
| 252 |
className={`flex-shrink-0 group relative rounded-2xl overflow-hidden border-2 transition-all duration-200 ${
|
| 253 |
segmentFilename === item.filename
|
| 254 |
? "border-[#0047AB] shadow-lg shadow-[#0047AB]/20"
|
|
|
|
| 293 |
Continuar <ArrowRight className="w-3.5 h-3.5" />
|
| 294 |
</span>
|
| 295 |
</div>
|
| 296 |
+
</div>
|
| 297 |
))}
|
| 298 |
</div>
|
| 299 |
</section>
|
frontend/src/features/roomSetup/roomSetupHooks.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
| 8 |
} from "react";
|
| 9 |
import { useNavigate } from "react-router-dom";
|
| 10 |
import useAppStore, { useHistoryStore } from "../../store/useAppStore";
|
|
|
|
| 11 |
|
| 12 |
export function useRoomSetup(): {
|
| 13 |
isDragging: boolean;
|
|
@@ -54,6 +55,22 @@ export function useRoomSetup(): {
|
|
| 54 |
setUploadMessage("Imagen lista — selecciona un producto para aplicar");
|
| 55 |
setUploadedFile(file);
|
| 56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
try {
|
| 58 |
// Ahora el flujo es: usuario sube imagen → selecciona producto → backend /api/generate-image
|
| 59 |
// Navegamos al visualizador con la preview local y el usuario selecciona producto allí.
|
|
|
|
| 8 |
} from "react";
|
| 9 |
import { useNavigate } from "react-router-dom";
|
| 10 |
import useAppStore, { useHistoryStore } from "../../store/useAppStore";
|
| 11 |
+
import { uploadRoomImage, buildApiUrl } from "../../api/client";
|
| 12 |
|
| 13 |
export function useRoomSetup(): {
|
| 14 |
isDragging: boolean;
|
|
|
|
| 55 |
setUploadMessage("Imagen lista — selecciona un producto para aplicar");
|
| 56 |
setUploadedFile(file);
|
| 57 |
|
| 58 |
+
// Start uploading in background so backend has a stable URL for processing.
|
| 59 |
+
(async () => {
|
| 60 |
+
try {
|
| 61 |
+
const res = await uploadRoomImage(file);
|
| 62 |
+
if (res?.url) {
|
| 63 |
+
const serverUrl = buildApiUrl(res.url as string);
|
| 64 |
+
setPreviewImage(serverUrl);
|
| 65 |
+
setUploadMessage("Imagen subida al servidor");
|
| 66 |
+
}
|
| 67 |
+
} catch (err) {
|
| 68 |
+
const msg =
|
| 69 |
+
err instanceof Error ? err.message : "Error al subir la imagen";
|
| 70 |
+
setUploadMessage(msg);
|
| 71 |
+
}
|
| 72 |
+
})();
|
| 73 |
+
|
| 74 |
try {
|
| 75 |
// Ahora el flujo es: usuario sube imagen → selecciona producto → backend /api/generate-image
|
| 76 |
// Navegamos al visualizador con la preview local y el usuario selecciona producto allí.
|
frontend/src/features/roomVisualizer/RoomVisualizer.tsx
CHANGED
|
@@ -168,10 +168,31 @@ export default function RoomVisualizer() {
|
|
| 168 |
|
| 169 |
const applyTextureWith = useCallback(
|
| 170 |
async (texturePath: string) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
// Si el usuario subió una imagen en esta sesión, preferimos usar el endpoint OpenAI
|
| 172 |
if (uploadedFile) {
|
| 173 |
try {
|
| 174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 175 |
if (data?.url) {
|
| 176 |
setCurrentPreviewImage(data.url);
|
| 177 |
}
|
|
@@ -898,6 +919,51 @@ export default function RoomVisualizer() {
|
|
| 898 |
flexDirection: "column",
|
| 899 |
}}
|
| 900 |
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 901 |
{isMobile ? (
|
| 902 |
// ── Layout Mobile: imagen arriba, strip de thumbnails abajo ──────────
|
| 903 |
<div
|
|
|
|
| 168 |
|
| 169 |
const applyTextureWith = useCallback(
|
| 170 |
async (texturePath: string) => {
|
| 171 |
+
if (isApplying) {
|
| 172 |
+
Swal.fire(
|
| 173 |
+
"Espera",
|
| 174 |
+
"Ya hay una operación en curso. Espera a que termine.",
|
| 175 |
+
"info",
|
| 176 |
+
);
|
| 177 |
+
return;
|
| 178 |
+
}
|
| 179 |
// Si el usuario subió una imagen en esta sesión, preferimos usar el endpoint OpenAI
|
| 180 |
if (uploadedFile) {
|
| 181 |
try {
|
| 182 |
+
// If the image was already uploaded to server, prefer passing the server filename (avoid sending generated previews)
|
| 183 |
+
const serverUrl = state?.previewImage ?? storedPreviewImage ?? null;
|
| 184 |
+
let source: File | string = uploadedFile;
|
| 185 |
+
// If preview points to uploads path, extract filename and send it instead
|
| 186 |
+
if (
|
| 187 |
+
typeof serverUrl === "string" &&
|
| 188 |
+
serverUrl.includes("/uploads/")
|
| 189 |
+
) {
|
| 190 |
+
// serverUrl may be e.g. "http://localhost:8000/uploads/<filename>" or "/uploads/<filename>"
|
| 191 |
+
const idx = serverUrl.lastIndexOf("/uploads/");
|
| 192 |
+
const filename = serverUrl.substring(idx + "/uploads/".length);
|
| 193 |
+
source = filename;
|
| 194 |
+
}
|
| 195 |
+
const data = await applyTextureOpenAI(source, texturePath);
|
| 196 |
if (data?.url) {
|
| 197 |
setCurrentPreviewImage(data.url);
|
| 198 |
}
|
|
|
|
| 919 |
flexDirection: "column",
|
| 920 |
}}
|
| 921 |
>
|
| 922 |
+
{isApplying && (
|
| 923 |
+
<div
|
| 924 |
+
aria-hidden={!isApplying}
|
| 925 |
+
style={{
|
| 926 |
+
position: "fixed",
|
| 927 |
+
inset: 0,
|
| 928 |
+
display: "flex",
|
| 929 |
+
alignItems: "center",
|
| 930 |
+
justifyContent: "center",
|
| 931 |
+
background: "rgba(0,0,0,0.45)",
|
| 932 |
+
zIndex: 9999,
|
| 933 |
+
backdropFilter: "blur(2px)",
|
| 934 |
+
WebkitBackdropFilter: "blur(2px)",
|
| 935 |
+
}}
|
| 936 |
+
>
|
| 937 |
+
<div
|
| 938 |
+
style={{
|
| 939 |
+
display: "flex",
|
| 940 |
+
flexDirection: "column",
|
| 941 |
+
alignItems: "center",
|
| 942 |
+
gap: 12,
|
| 943 |
+
padding: 20,
|
| 944 |
+
borderRadius: 12,
|
| 945 |
+
background: "rgba(255,255,255,0.98)",
|
| 946 |
+
boxShadow: "0 6px 24px rgba(0,0,0,0.3)",
|
| 947 |
+
minWidth: 220,
|
| 948 |
+
}}
|
| 949 |
+
>
|
| 950 |
+
<div
|
| 951 |
+
style={{
|
| 952 |
+
width: 48,
|
| 953 |
+
height: 48,
|
| 954 |
+
borderRadius: 24,
|
| 955 |
+
border: "4px solid #e6e6e6",
|
| 956 |
+
borderTopColor: "#0047AB",
|
| 957 |
+
animation: "hr-spin 1s linear infinite",
|
| 958 |
+
}}
|
| 959 |
+
/>
|
| 960 |
+
<div style={{ fontSize: 14, color: "#111", textAlign: "center" }}>
|
| 961 |
+
Generando imagen… Por favor espera
|
| 962 |
+
</div>
|
| 963 |
+
</div>
|
| 964 |
+
<style>{`@keyframes hr-spin { from { transform: rotate(0deg) } to { transform: rotate(360deg) } }`}</style>
|
| 965 |
+
</div>
|
| 966 |
+
)}
|
| 967 |
{isMobile ? (
|
| 968 |
// ── Layout Mobile: imagen arriba, strip de thumbnails abajo ──────────
|
| 969 |
<div
|
frontend/src/hooks/useApplyTexture.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
import { useCallback, useState } from "react";
|
| 2 |
import { API_BASE } from "../api/client";
|
|
|
|
| 3 |
|
| 4 |
interface ApplyTextureResult {
|
| 5 |
output_url: string;
|
|
@@ -125,13 +126,31 @@ export function useApplyTexture() {
|
|
| 125 |
);
|
| 126 |
|
| 127 |
const applyTextureOpenAI = useCallback(
|
| 128 |
-
async (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
setIsApplying(true);
|
| 130 |
setError(null);
|
| 131 |
try {
|
| 132 |
const form = new FormData();
|
| 133 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
form.append("texture", textureName);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
if (apiKey) form.append("api_key", apiKey);
|
| 136 |
|
| 137 |
const res = await fetch(`${API_BASE}/api/generate-image`, {
|
|
|
|
| 1 |
import { useCallback, useState } from "react";
|
| 2 |
import { API_BASE } from "../api/client";
|
| 3 |
+
import { useHistoryStore } from "../store/useAppStore";
|
| 4 |
|
| 5 |
interface ApplyTextureResult {
|
| 6 |
output_url: string;
|
|
|
|
| 126 |
);
|
| 127 |
|
| 128 |
const applyTextureOpenAI = useCallback(
|
| 129 |
+
async (
|
| 130 |
+
fileOrFilename: File | string,
|
| 131 |
+
textureName: string,
|
| 132 |
+
apiKey?: string | null,
|
| 133 |
+
) => {
|
| 134 |
+
if (isApplying) throw new Error("Ya hay una operación en curso");
|
| 135 |
setIsApplying(true);
|
| 136 |
setError(null);
|
| 137 |
try {
|
| 138 |
const form = new FormData();
|
| 139 |
+
// Accept either a File object (client-side upload) or a server filename (string)
|
| 140 |
+
if (typeof fileOrFilename === "string") {
|
| 141 |
+
// server-side filename returned by uploadRoomImage, e.g. "/uploads/abcd.png" or full URL
|
| 142 |
+
const name = fileOrFilename.includes("/uploads/")
|
| 143 |
+
? fileOrFilename.split("/uploads/").pop() || fileOrFilename
|
| 144 |
+
: fileOrFilename;
|
| 145 |
+
form.append("source_filename", name);
|
| 146 |
+
} else {
|
| 147 |
+
form.append("file", fileOrFilename);
|
| 148 |
+
}
|
| 149 |
form.append("texture", textureName);
|
| 150 |
+
const userId =
|
| 151 |
+
useHistoryStore.getState?.()?.userId ??
|
| 152 |
+
useHistoryStore((s) => s.userId);
|
| 153 |
+
if (userId) form.append("user_id", userId);
|
| 154 |
if (apiKey) form.append("api_key", apiKey);
|
| 155 |
|
| 156 |
const res = await fetch(`${API_BASE}/api/generate-image`, {
|
frontend/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
export const appVersion = "0.1.0-dev.
|
|
|
|
| 1 |
+
export const appVersion = "0.1.0-dev.20260512T030125";
|