browser-assistant 0.0.0-stage → 2.8.2

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-present Browser Assistant Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,121 @@
1
- # Temporary Holding Version
1
+ # Browser Assistant
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A Chrome Manifest V3 extension with a local Python backend for exploring multiple-choice questions and coding exercises on webpages. Built for learners reviewing answers and developers experimenting with automation on pages they own or have permission to operate.
4
+
5
+ ## What it does
6
+
7
+ - Extracts page text and requests answers from Groq, with Ollama fallback for text requests.
8
+ - Captures the visible browser tab for Groq vision analysis.
9
+ - Detects requested programming languages and validates generated code syntax; model review does not prove correctness.
10
+ - Displays results in an in-page panel, offers code copying, and saves successful scans in local SQLite history.
11
+ - Includes a local practice page and automation for selecting answers, filling editors, and submitting supported forms after starting a run.
12
+ - Resumes CCBP practice from an already submitted answer through its submitted-question Next control, without generating or submitting that answer again. Delayed Submit controls are awaited for up to 15 seconds while the question and selected answer remain unchanged.
13
+ - Press **Alt + Shift + A** on the webpage to start automation, then press it again to pause or resume. It also works with the code editor focused and opens QA Control. Journal automation uses the same toggle; its existing **Alt + Shift + J** shortcut remains available.
14
+
15
+ AI answers can be wrong. Automation can change or submit page content: use it only where authorized, review results, and avoid restricted assessments. Site detection is heuristic; custom controls, frames, editors, and navigation can fail. The policy includes a general HTTP/HTTPS fallback, so it is not a strict site allowlist.
16
+
17
+ ## First run
18
+
19
+ ### Continuous coding batch
20
+
21
+ On CCBP `/problems-set`, start on page 1 and keep both **Not Attempted** and
22
+ **In Progress** visible in the status filters. Choose **QA Control → Start automation**.
23
+ The batch skips Solved rows, opens an eligible question, reads its language and
24
+ existing code, generates and submits a solution, and returns to the list only after
25
+ a confirmed passing result. It follows numbered pages within the selected filters.
26
+ Keep the browser tab and local AI server open; Pause/Resume and Stop are available.
27
+ Failed tests, unsupported layouts, or unconfirmed results stop the batch with a reason.
28
+ Reloading during solving/submission stops rather than submitting twice. Starting on
29
+ a single question still solves just that question. Batch behavior has fixture tests;
30
+ completion on the live portal has not been verified.
31
+
32
+ Use Chrome, Python **3.11+**, and either a Groq key or an installed Ollama model for text scans. Building from source or running contributor tests requires Node.js **22.18+**. Chrome internal pages cannot run content scripts; other Chromium browsers are not verified here. Firefox is not supported by this manifest.
33
+
34
+ ### Install and update with npm
35
+
36
+ In a dedicated folder, run `npm init -y` and then `npm install browser-assistant`. The package includes the compiled Chrome extension and the local Python backend.
37
+
38
+ 1. Open `chrome://extensions`, enable **Developer mode**, choose **Load unpacked**, and select `node_modules/browser-assistant/extension` inside your folder.
39
+ 2. Create and activate a Python 3.11+ virtual environment in your folder. Install the backend dependencies with `python -m pip install --require-hashes -r node_modules/browser-assistant/server/requirements.lock.txt`.
40
+ 3. Copy `node_modules/browser-assistant/server/.env.example` to `.env` in your folder. Set `HISTORY_DB_PATH=./scan_history.db` in that copy and configure a provider as described below. Keep this file and the database beside `node_modules` so they persist across upgrades.
41
+ 4. From your folder, start the backend with `python -m uvicorn --app-dir node_modules/browser-assistant/server --env-file .env --host 127.0.0.1 --port 8000 main:app`. Check `http://127.0.0.1:8000/health`.
42
+
43
+ If you're moving from a ZIP install, copy your existing `server/.env` and `server/scan_history.db`, if present, into the new folder to keep your provider settings and scan history.
44
+
45
+ To upgrade, stop the backend and run `npm install browser-assistant@latest` from the same folder. Rerun the Python dependency install, restart the backend, and click **Reload** on the extension card in `chrome://extensions`. Refresh any open tabs where you use the extension.
46
+
47
+ ### Install from GitHub
48
+
49
+ Download the backend ZIP or clone this repository, then open a terminal in the extracted backend folder or repository root. Versioned extension, backend, and source ZIPs with SHA-256 checksums are available on the [GitHub Releases page](https://github.com/JaswanthCodeHub/browser-assistant/releases).
50
+
51
+ ### Windows PowerShell
52
+
53
+ ```powershell
54
+ py -3.11 -m venv .venv
55
+ .\.venv\Scripts\python.exe -m pip install --require-hashes -r server\requirements.lock.txt
56
+ Copy-Item server\.env.example server\.env
57
+ # Edit server\.env as described below, then:
58
+ Set-Location server
59
+ ..\.venv\Scripts\python.exe main.py
60
+ ```
61
+
62
+ ### macOS / Linux
63
+
64
+ ```bash
65
+ python3.11 -m venv .venv
66
+ .venv/bin/python -m pip install --require-hashes -r server/requirements.lock.txt
67
+ cp server/.env.example server/.env
68
+ # Edit server/.env as described below, then:
69
+ cd server
70
+ ../.venv/bin/python main.py
71
+ ```
72
+
73
+ Python 3.12 or 3.14 can replace 3.11. Pillow 13 security fixes require Python 3.11+, so Python 3.10 is no longer in the secure installation matrix. Existing users on 3.11+ keep their runtime. These commands avoid shell activation requirements. Do not overwrite an existing `.env` or environment when updating a local installation.
74
+
75
+ ### Configure a provider
76
+
77
+ For cloud inference, set `GROQ_API_KEY` in your `.env` to your own key from [Groq Console](https://console.groq.com/). Text and vision model IDs are configurable; provider availability and account access can change. The example matches implementation defaults, not a guarantee that a model is available to your account.
78
+
79
+ For local text inference, install [Ollama](https://github.com/ollama/ollama), run `ollama pull llama3`, and ensure its service is running. Leave all Groq key fields empty to keep text inference on Ollama; when a Groq key is present, Groq is tried first. Set `OLLAMA_MODEL` to an installed model name. Vision scans require Groq and have no Ollama fallback. See [configuration and troubleshooting](docs/SETUP.md).
80
+
81
+ ### Install and try the extension
82
+
83
+ 1. Extract the extension ZIP from Releases. If using a clone or the source ZIP, run `npm ci` and `npm run build` from its root to prepare the `extension` folder.
84
+ 2. Open `chrome://extensions`, enable **Developer mode**, choose **Load unpacked**, and select the prepared folder containing `manifest.json`.
85
+ 3. Open `http://127.0.0.1:8000/health`. A JSON `status: "ok"` confirms the backend is running; it does not test model access.
86
+ 4. Open `http://127.0.0.1:8000/practice`, then use the floating panel's Text Scan. Review the answer before trying automation with Start.
87
+ 5. After changing extension files, reload it in the extensions page and refresh the practice tab.
88
+
89
+ The toolbar popup reports backend status. In-page shortcuts are backtick (open), `]` (close), `\` (vision scan), and `[` (minimal mode). They are hardcoded page listeners, not configurable Chrome extension commands.
90
+
91
+ ## Data and permissions
92
+
93
+ The backend binds to `127.0.0.1:8000` by default and has **no authentication**. Keep it local. Its address is fixed in the extension.
94
+
95
+ The manifest requests `activeTab`, `tabs`, `scripting`, and `clipboardWrite`, plus access to all URLs and localhost. Content scripts run on matching pages; scripting bridges supported page editors, tabs support capture and messaging, and clipboard access supports code copying. These are broad permissions; install only if you accept page access.
96
+
97
+ Text scans send extracted text and the current URL to the backend. Groq receives model prompts containing question text; vision scans capture the entire visible tab, compress the image, and send it to Groq. Sensitive content visible in a tab may therefore leave your machine. There is no screenshot redaction step. The application does not explicitly save raw screenshots to disk; request data exists in memory, and providers have their own retention policies.
98
+
99
+ Successful scans are saved by the extension through `/history`: URL, timestamp, scan type, provider, language, and answer JSON are kept in `server/scan_history.db`, capped at 100 entries. Clear History deletes rows, not a forensic secure erase. Stop the backend and remove the database and its `-wal`/`-shm` companions for file-level removal; backups may still contain data. Panel position uses the page's localStorage, and automation resume state uses its sessionStorage. Clear site data to remove those settings. Minimal/stealth controls change presentation; they do not guarantee invisibility or privacy.
100
+
101
+ ## Development and Docker
102
+
103
+ From the repository root:
104
+
105
+ ```bash
106
+ npm ci
107
+ npm test
108
+ python scripts/check_repo.py
109
+ ```
110
+
111
+ Edit the TypeScript sources in `extension/src/`. Run `npm run build` to regenerate the JavaScript used by Chrome before reloading the unpacked extension. `npm test` builds and type-checks the extension before running its tests.
112
+
113
+ Use your environment's Python for the last command. Backend checks and Docker instructions are in [CONTRIBUTING.md](CONTRIBUTING.md) and [SETUP.md](docs/SETUP.md). `server/requirements.lock.txt` pins the full dependency graph with package hashes; `requirements.txt` records the direct dependencies. Use the lockfile for installation. The [repair report](docs/REPAIR_REPORT.md) distinguishes automated checks from unverified live integrations.
114
+
115
+ ## Get involved
116
+
117
+ Small, focused contributions are welcome. Start with the [contribution guide](CONTRIBUTING.md) and [roadmap](docs/ROADMAP.md). Read the [code of conduct](CODE_OF_CONDUCT.md) and [security policy](SECURITY.md) before reporting problems.
118
+
119
+ [API](docs/API.md) · [Architecture](docs/ARCHITECTURE.md) · [Changelog](CHANGELOG.md) · [Launch checklist](docs/LAUNCH.md)
120
+
121
+ Licensed under the [MIT license](LICENSE). The existing attribution is preserved; the repository owner must confirm rights to publish before launch.
@@ -0,0 +1,58 @@
1
+ // Retry answer generation only. Selection and submission are never retried here.
2
+ (function () {
3
+ function failure(response) {
4
+ const detail = response?.data?.detail;
5
+ let message = typeof detail === 'string' ? detail : detail?.message || response?.error || 'Answer service did not respond';
6
+ if (Array.isArray(detail))
7
+ message = detail.map(item => item.msg || String(item)).join('; ');
8
+ if (Array.isArray(detail?.errors))
9
+ message += `: ${detail.errors.join(' | ')}`;
10
+ message = String(message).replace(/gsk_[\w]+|sk-[\w-]+/g, '[redacted]').slice(0, 900);
11
+ const error = new Error(`${response?.status ? `HTTP ${response.status}: ` : ''}${message}`);
12
+ error.status = response?.status;
13
+ return error;
14
+ }
15
+ function temporary(error) {
16
+ const text = error?.message || '';
17
+ if (/access denied|forbidden|unauthorized|invalid.api.key|not configured|validation|not.support|model.*(?:not found|not exist)|illustration changed|question changed|context invalidated|extension was reloaded|no readable|unparseable/i.test(text))
18
+ return false;
19
+ if (error.status)
20
+ return [408, 425, 429, 500, 502, 503, 504].includes(error.status);
21
+ return /network|fetch|offline|timed?\s*out|timeout|did not respond|connection|temporar|background script did not respond|message port closed|message channel closed/i.test(text);
22
+ }
23
+ async function run({ request, active, current, ready, onRetry, sleep }) {
24
+ const attempts = 3;
25
+ for (let attempt = 1; attempt <= attempts; attempt++) {
26
+ if (!active() || !(await ready()) || !active())
27
+ return null;
28
+ if (!current())
29
+ throw new Error('Question changed while requesting an answer. No answer was selected.');
30
+ try {
31
+ const response = await request();
32
+ if (!active() || !(await ready()) || !active())
33
+ return null;
34
+ if (!current())
35
+ throw new Error('Question changed while requesting an answer. No answer was selected.');
36
+ if (!response?.ok)
37
+ throw failure(response);
38
+ return response;
39
+ }
40
+ catch (error) {
41
+ if (!active())
42
+ return null;
43
+ if (attempt === attempts || !temporary(error))
44
+ throw error;
45
+ onRetry({ attempt: attempt + 1, attempts, message: error.message });
46
+ // Short waits keep Stop/Pause responsive. Revalidate before the
47
+ // next request so an old answer cannot target a new question.
48
+ const delay = attempt === 1 ? 1000 : 2500;
49
+ for (let elapsed = 0; elapsed < delay; elapsed += 100) {
50
+ if (!active())
51
+ return null;
52
+ await sleep(100);
53
+ }
54
+ }
55
+ }
56
+ }
57
+ window.BrowserAssistantAnswerRequests = Object.freeze({ run, failure, temporary });
58
+ })();