browse-code 0.2.19__tar.gz → 0.2.21__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. {browse_code-0.2.19 → browse_code-0.2.21}/PKG-INFO +1 -1
  2. browse_code-0.2.21/browse_code/__init__.py +1 -0
  3. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code/extension/content.js +39 -4
  4. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code/server.py +30 -0
  5. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code.egg-info/PKG-INFO +1 -1
  6. {browse_code-0.2.19 → browse_code-0.2.21}/setup.py +1 -1
  7. browse_code-0.2.19/browse_code/__init__.py +0 -1
  8. {browse_code-0.2.19 → browse_code-0.2.21}/README.md +0 -0
  9. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code/cli.py +0 -0
  10. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code/extension/icon128.png +0 -0
  11. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code/extension/icon16.png +0 -0
  12. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code/extension/icon48.png +0 -0
  13. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code/extension/manifest.json +0 -0
  14. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code/extension/popup.html +0 -0
  15. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code/extension/popup.js +0 -0
  16. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code/extension/spoof.js +0 -0
  17. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code.egg-info/SOURCES.txt +0 -0
  18. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code.egg-info/dependency_links.txt +0 -0
  19. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code.egg-info/entry_points.txt +0 -0
  20. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code.egg-info/requires.txt +0 -0
  21. {browse_code-0.2.19 → browse_code-0.2.21}/browse_code.egg-info/top_level.txt +0 -0
  22. {browse_code-0.2.19 → browse_code-0.2.21}/pyproject.toml +0 -0
  23. {browse_code-0.2.19 → browse_code-0.2.21}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: browse_code
3
- Version: 0.2.19
3
+ Version: 0.2.21
4
4
  Summary: Turn any AI chatbot into an autonomous coding agent
5
5
  Description-Content-Type: text/markdown
6
6
  Requires-Dist: fastapi
@@ -0,0 +1 @@
1
+ __version__ = "0.2.21"
@@ -67,6 +67,7 @@ GOLDEN RULES (violating any of these breaks the session)
67
67
  If you ever see a terminal_run timeout error, do NOT re-run the same command with terminal_run again — restart it via terminal_bg instead.
68
68
  terminal_run is only appropriate for short, fast, deterministic commands you're confident finish in a few seconds (e.g. ls, cat, a single quick lint check, git status).
69
69
  8. If a result is [TRUNCATED] or a file is large, narrow down with search_code or read_lines instead of re-requesting the whole file.
70
+ 9. **Image Generation:** If you generate an image in chat, the bridge will automatically download it to \`agent-creations/\` in the workspace and notify you with the local file path. You can then use this path in code (e.g. as a UI asset or mockup). Do NOT try to download images yourself using terminal commands.
70
71
 
71
72
  ═══════════════════════════════════════
72
73
  WORKFLOW: "Autonomous Researcher"
@@ -251,7 +252,6 @@ async function injectAndSend(promptText) {
251
252
  // Setup an aggressive retry loop that clicks it the moment they focus the tab and React wakes up.
252
253
  const clickInterval = setInterval(() => {
253
254
  const currentText = inputBox.tagName === 'INPUT' || inputBox.tagName === 'TEXTAREA' ? inputBox.value : inputBox.textContent;
254
- // Abort if the user manually cleared or changed the input significantly
255
255
  if (!currentText || currentText.length < promptText.length * 0.5) {
256
256
  clearInterval(clickInterval);
257
257
  return;
@@ -261,7 +261,6 @@ async function injectAndSend(promptText) {
261
261
  }
262
262
  }, 500);
263
263
 
264
- // Clear interval after 15 seconds to avoid infinite loops
265
264
  setTimeout(() => clearInterval(clickInterval), 15000);
266
265
  }
267
266
  }
@@ -350,11 +349,47 @@ function trackResponse(initialText) {
350
349
 
351
350
  // If text has not changed for 2.5 seconds (5 ticks), assume generation is complete!
352
351
  if (unchangedTicks > 4) {
352
+
353
+ // Auto-save generated images
354
+ try {
355
+ const responseBlocks = document.querySelectorAll(PLATFORM.responseContainer);
356
+ if (responseBlocks.length > 0) {
357
+ const latestBlock = responseBlocks[responseBlocks.length - 1];
358
+ const images = latestBlock.querySelectorAll('img');
359
+ for (const img of images) {
360
+ if (img.dataset.agentProcessed) continue;
361
+ img.dataset.agentProcessed = "true";
362
+
363
+ // Filter out icons, avatars, and SVGs
364
+ if (img.src.includes('.svg') || img.src.includes('avatar') || img.src.includes('favicon')) continue;
365
+ if (img.width > 0 && img.width < 100) continue;
366
+
367
+ fetch(img.src)
368
+ .then(res => res.blob())
369
+ .then(blob => {
370
+ const reader = new FileReader();
371
+ reader.onloadend = () => {
372
+ fetch(`${LOCAL_SERVER}/extension/save-image`, {
373
+ method: 'POST',
374
+ headers: { 'Content-Type': 'application/json' },
375
+ body: JSON.stringify({ base64: reader.result })
376
+ }).then(res => res.json()).then(data => {
377
+ if (data.status === 'ok') {
378
+ messageQueue.push(`[System - Image Saved]: An image you generated was automatically downloaded and saved to: ${data.path}\nYou can use this file path in your code if you need to.`);
379
+ }
380
+ }).catch(err => console.error(err));
381
+ };
382
+ reader.readAsDataURL(blob);
383
+ }).catch(err => console.error("Failed to fetch image blob", err));
384
+ }
385
+ }
386
+ } catch (err) {
387
+ console.error("Image processing error", err);
388
+ }
389
+
353
390
  clearInterval(trackInterval);
354
391
  lastContainer.setAttribute('data-agent-processed', 'true');
355
392
  isWaitingForLLM = false; // UNLOCK IMMEDIATELY to prevent deadlocks from long-running tools
356
-
357
-
358
393
  const toolMatches = currentText.match(/<tool=[\s\S]*?<\/tool>/g);
359
394
  if (toolMatches && toolMatches.length > 0) {
360
395
  try {
@@ -184,6 +184,36 @@ async def extension_ping(v: str = None):
184
184
  print(f"\n{C_OK}[+] Extension connected{C_RESET}")
185
185
  return {"status": "ok"}
186
186
 
187
+ class ImageModel(BaseModel):
188
+ base64: str
189
+
190
+ @app.post("/extension/save-image")
191
+ async def save_image(data: ImageModel):
192
+ import base64
193
+ try:
194
+ header, encoded = data.base64.split(",", 1)
195
+ ext = "png"
196
+ if "jpeg" in header or "jpg" in header:
197
+ ext = "jpg"
198
+ elif "webp" in header:
199
+ ext = "webp"
200
+
201
+ image_data = base64.b64decode(encoded)
202
+ creations_dir = os.path.join(WORKSPACE_DIR, "agent-creations")
203
+ os.makedirs(creations_dir, exist_ok=True)
204
+
205
+ filename = f"generated_{uuid.uuid4().hex[:8]}.{ext}"
206
+ filepath = os.path.join(creations_dir, filename)
207
+
208
+ with open(filepath, "wb") as f:
209
+ f.write(image_data)
210
+
211
+ rel_path = f"agent-creations/{filename}"
212
+ print(f"\n{C_OK}[+] Saved AI image to {rel_path}{C_RESET}")
213
+ return {"status": "ok", "path": rel_path}
214
+ except Exception as e:
215
+ return {"status": "error", "message": str(e)}
216
+
187
217
  def cleanup_background_processes():
188
218
  print(f"\n{C_WARN}⏻ Shutting down — cleaning up background processes...{C_RESET}")
189
219
  for pid, data in BACKGROUND_PROCESSES.items():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: browse_code
3
- Version: 0.2.19
3
+ Version: 0.2.21
4
4
  Summary: Turn any AI chatbot into an autonomous coding agent
5
5
  Description-Content-Type: text/markdown
6
6
  Requires-Dist: fastapi
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="browse_code",
5
- version="0.2.19",
5
+ version="0.2.21",
6
6
  description="Turn any AI chatbot into an autonomous coding agent",
7
7
  long_description=open("README.md").read(),
8
8
  long_description_content_type="text/markdown",
@@ -1 +0,0 @@
1
- __version__ = "0.2.19"
File without changes
File without changes