localagentbrowser 1.62__tar.gz → 1.64__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 (47) hide show
  1. {localagentbrowser-1.62 → localagentbrowser-1.64}/CHANGELOG.md +152 -1
  2. {localagentbrowser-1.62/localagentbrowser.egg-info → localagentbrowser-1.64}/PKG-INFO +95 -22
  3. {localagentbrowser-1.62 → localagentbrowser-1.64}/README.md +94 -21
  4. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser/agent.py +101 -20
  5. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser/checks.py +176 -7
  6. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser/config.py +17 -0
  7. localagentbrowser-1.64/localagentbrowser/coverage.py +372 -0
  8. localagentbrowser-1.64/localagentbrowser/grounding.py +233 -0
  9. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser/pages.py +119 -10
  10. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser/prompts.py +40 -2
  11. localagentbrowser-1.64/localagentbrowser/report.py +835 -0
  12. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser/text.py +15 -0
  13. {localagentbrowser-1.62 → localagentbrowser-1.64/localagentbrowser.egg-info}/PKG-INFO +95 -22
  14. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser.egg-info/SOURCES.txt +3 -1
  15. {localagentbrowser-1.62 → localagentbrowser-1.64}/pyproject.toml +1 -1
  16. {localagentbrowser-1.62 → localagentbrowser-1.64}/tests/fakes.py +4 -2
  17. {localagentbrowser-1.62 → localagentbrowser-1.64}/tests/golden/prompts.json +142 -132
  18. localagentbrowser-1.64/tests/test_checklist.py +926 -0
  19. localagentbrowser-1.64/tests/test_decisions.py +701 -0
  20. {localagentbrowser-1.62 → localagentbrowser-1.64}/tests/test_golden_prompts.py +2 -1
  21. {localagentbrowser-1.62 → localagentbrowser-1.64}/tests/test_main_loop.py +13 -11
  22. {localagentbrowser-1.62 → localagentbrowser-1.64}/tests/test_model_turns.py +102 -2
  23. localagentbrowser-1.64/tests/test_page_text.py +165 -0
  24. {localagentbrowser-1.62 → localagentbrowser-1.64}/tests/test_regression.py +91 -0
  25. localagentbrowser-1.64/tests/test_show_report.py +30 -0
  26. {localagentbrowser-1.62 → localagentbrowser-1.64}/tools/regression.py +171 -22
  27. localagentbrowser-1.64/tools/windows/show_report.py +155 -0
  28. localagentbrowser-1.62/localagentbrowser/coverage.py +0 -175
  29. localagentbrowser-1.62/localagentbrowser/grounding.py +0 -121
  30. localagentbrowser-1.62/localagentbrowser/report.py +0 -208
  31. localagentbrowser-1.62/tests/test_checklist.py +0 -346
  32. localagentbrowser-1.62/tests/test_decisions.py +0 -368
  33. localagentbrowser-1.62/tests/test_page_text.py +0 -88
  34. {localagentbrowser-1.62 → localagentbrowser-1.64}/LICENSE +0 -0
  35. {localagentbrowser-1.62 → localagentbrowser-1.64}/MANIFEST.in +0 -0
  36. {localagentbrowser-1.62 → localagentbrowser-1.64}/agent_browser.py +0 -0
  37. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser/__init__.py +0 -0
  38. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser/checklist.py +0 -0
  39. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser.egg-info/dependency_links.txt +0 -0
  40. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser.egg-info/entry_points.txt +0 -0
  41. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser.egg-info/requires.txt +0 -0
  42. {localagentbrowser-1.62 → localagentbrowser-1.64}/localagentbrowser.egg-info/top_level.txt +0 -0
  43. {localagentbrowser-1.62 → localagentbrowser-1.64}/setup.cfg +0 -0
  44. {localagentbrowser-1.62 → localagentbrowser-1.64}/tests/conftest.py +0 -0
  45. {localagentbrowser-1.62 → localagentbrowser-1.64}/tests/test_duplicates.py +0 -0
  46. {localagentbrowser-1.62 → localagentbrowser-1.64}/tests/test_journal.py +0 -0
  47. {localagentbrowser-1.62 → localagentbrowser-1.64}/tools/live_test.py +0 -0
@@ -1,11 +1,162 @@
1
1
  # Changelog
2
2
 
3
- Every version of LocalAgentBrowser, newest first. Each released version is also a tagged commit (`v1.11` … `v1.62`); 1.54 to 1.56 and 1.58 to 1.60 were internal steps
3
+ Every version of LocalAgentBrowser, newest first. Each released version is also a tagged commit (`v1.11` … `v1.63`); 1.54 to 1.56 and 1.58 to 1.60 were internal steps
4
4
  measured on the regression suite and released as part of 1.57 and 1.61 (see
5
5
  [docs/regression-history.md](docs/regression-history.md)).
6
6
  Timings are from live runs on the development machine (Intel i5-9500, 6 cores, no GPU, Qwen2.5-7B-Instruct
7
7
  Q4_K_M in LM Studio), where reading the prompt takes about 90% of every model call.
8
8
 
9
+ ## [1.64] - 2026-11-08
10
+ The theme is **silent omission** ([issue #11](https://github.com/SnowFXXX/LocalAgentBrowser/issues/11)): a part of
11
+ the objective dropping out of the final answer without being marked "not found". It was measured on two PCs (PC A
12
+ and PC B, both Intel i5-9500, no GPU) and then on four models with identical code.
13
+
14
+ ### Added
15
+ - **Windows launcher and shortcuts.** `tools/windows/LocalAgentBrowser.cmd` checks that LM Studio is answering,
16
+ runs the agent in its own folder under `Documents\LocalAgentBrowser runs`, and opens the report when the run ends.
17
+ `tools/windows/make_shortcuts.ps1` adds Start-menu and desktop shortcuts with the project icon (from a clone of
18
+ the repository).
19
+ - **The report opens by itself** when a launcher run ends: `research_report.md` is written next to it as a dark web
20
+ page, in the project site's colors, with the final result, checklist and discoveries in separate cards and
21
+ citations shown as tags (`tools/windows/show_report.py`, standard library only). Windows has no program for `.md`
22
+ files by default.
23
+ - Regression suite: every run folder gets `run_info.json` (PC label from `LAB_PC_LABEL`, commit, and a fingerprint
24
+ of the uncommitted changes), so runs on several PCs can be tied to the exact code they ran.
25
+ - Regression suite: `LAB_BLOCKED_SITES` makes NAVIGATE refuse given sites, for benchmark runs that must not read the
26
+ benchmark's own answer pages.
27
+
28
+ ### Fixed: parts of the objective dropping out of the answer
29
+ - **The coverage check asks for the quote first.** "Does this discovery answer the item?" is now answered by first
30
+ copying the words that answer it, with a rule that words on the same topic but a different aspect don't count.
31
+ On 30 hand-labelled real cases, 25 right instead of 16 (no false "not found", 5 false "found" left).
32
+ - **A part credited to several items only counts where the item's own words appear**, so one quote can't silently
33
+ cover three parts; such an item is sent back as unanswered.
34
+ - **Missing amounts and concrete missing terms send the agent back.** When an item asks for amounts and no discovery
35
+ for it gives one, or the check names a concrete missing term ("O2") that no discovery contains, the agent is told
36
+ to find it, instead of finishing without it (an explanation once finished in 4 turns without oxygen).
37
+ - **Each fact stays under its own part.** A discovery keeps the page heading it came from, including headings inside
38
+ a discovery that crosses page sections; a heading the discovery starts with isn't replaced by the one above;
39
+ bylines, very long "headings" (numbered sentences) and the prompt's own section names don't count as headings or
40
+ names.
41
+ - **Names no discovery gives are cut,** with a note: a short cited heading's name is checked too, word forms need
42
+ an 80% shared start ("PhotoScape" over a PhotoSplice source), and words in a source's web address count as given.
43
+ - **A sentence under one label copied from another subject's sentence is cut** (SQLite's sentence under
44
+ PostgreSQL).
45
+ - **Numbers in words are checked like digits** ("two weeks" needs a 2 in a source, "one cup" equals "1 cup"), unit
46
+ abbreviations count as their words ("5,895 m (19,341 ft)" answers "in meters" and "in feet"), and a time needs
47
+ the same number as a time in a source ("2 weeks" was taken from a "2L jar").
48
+ - **Citations:** citation lines on their own are joined to the line they cite; citations are moved out of code, and
49
+ unclosed code blocks closed, so correct commands aren't cut as invented.
50
+ - A **"Recommendation" section is labelled as the model's view**, like "My view:".
51
+ - **NAVIGATE refuses text that isn't a web address** (a run lost 5 turns on it).
52
+
53
+ ### Fixed: the regression suite's scoring
54
+ - The code's own "Left out, because…" notes are no longer read as the result's claims (commands and uncited lines).
55
+ 4 of 78 earlier run folders were over-counted.
56
+ - A bold label ("**1. Creating a virtual environment:**") is a heading, not an uncited claim.
57
+
58
+ ### Measured
59
+ - 7B on two PCs: 7 of 7 on both PCs with v11 (297.8 and 269.6 model minutes), with no outside knowledge, invented
60
+ numbers or invented commands in any finished result.
61
+ - Four models, same code (v12, 90 minutes per task): Qwen2.5-7B 6 of 7, Llama 3.1 8B 7 of 7, Qwen2.5-14B 5 of 7,
62
+ Qwen2.5-3B 3 of 7. On 1.63 they were 6, 2, 2 and 0 of 7. No finished result used outside knowledge. Details in
63
+ docs/regression-history.md.
64
+
65
+ ## [1.63] - 2026-11-01
66
+ ### Added
67
+ - A model call the server fails is tried again after a wait (5, 15, 30, 60 and 120 seconds, about 4 minutes in all),
68
+ instead of ending the run. LM Studio loads a model by itself when a request names one that is not loaded, and
69
+ unloads idle ones, so this can carry a run through an unloaded model (tested) or, if the app comes back within
70
+ about 4 minutes, a restarted app (not yet tested). Tested live: with the model
71
+ unloaded in the middle of turn 2, LM Studio refused that call ("400 - Model unloaded by user or API request"), the
72
+ agent waited 5 seconds, LM Studio loaded the model again, and the run finished with the right answer (before, the
73
+ same unload ended the run). Only server failures are retried; that refusal is the one 400 that is.
74
+ - Regression suite: `--model` runs the tasks with another model LM Studio has; the model is loaded first and its
75
+ context length checked, so every model is measured under the same conditions, and the run's folder and summary
76
+ name it.
77
+ - Regression suite: honesty measures for each finished result: what it says was not found, the code's caveats,
78
+ gaps filled from the model's own knowledge ("the text does not specify, but it is generally recommended ..."),
79
+ numbers no discovery contains, uncited lines and citations of missing discoveries, in a table in every summary.
80
+ ### Fixed (from the first tests on other models: Qwen2.5 3B, Llama 3.1 8B, Qwen2.5 14B)
81
+ - A runaway reply no longer stalls a run. A 3B model kept writing one turn's reply for 10 minutes (2,500+ tokens,
82
+ where real replies are at most a few hundred) until the connection timed out, and the request was then sent again;
83
+ two of its tasks never got past one turn. A browsing reply is now capped at 600 tokens, a timeout is not retried
84
+ (the model is still writing, not lost), and the client's own silent retries are off.
85
+ - The final result is asked for in a required field, `{"result": "..."}`, like every browsing reply. Asked for plain
86
+ text, Llama 3.1 8B answered 3 of 6 results with a made-up tool call (`{"name": "get_mountain_info", ...}`), and a 3B
87
+ model "finished" a how-to with its own prompt repeated back. A reply that is still JSON or repeats the prompt's
88
+ sections is asked for once more; if that fails too, the report says no result was written and points to the
89
+ findings, instead of showing the broken reply as a result.
90
+ - A finding recorded on the search results page is refused: "NAVIGATE to the result that looks right and DISCOVER from
91
+ the page itself". A result's snippet is a summary written to be clicked, not a source; the 3B recorded snippets in 5
92
+ of 7 tasks, and every model did it at least once.
93
+ ### Fixed (from the full suite on four models, and an untimed suite on the 7B)
94
+ - **Commands are checked as exact text.** A command in a finding must be on the page shown. That covers text in
95
+ backticks, every line of a code block, and any path or placeholder (a backslash, `<venv>`, two slashes); prose
96
+ slashes such as "macOS/Linux" and web addresses are not counted. Word-by-word matching cannot see a wrong
97
+ command:
98
+ - The 7B recorded `pip install package_name`, which the page never gives. It scored 60% against the page, above
99
+ the two lines it really copied, because its words repeat the objective.
100
+ - Copying the official venv activation table, it swapped `bin` and `Scripts` (`C:\> <venv>\bin\activate.bat`)
101
+ in two runs.
102
+
103
+ Across every earlier suite run, 21 of 525 findings fail this check, all on the documentation task and all real.
104
+ The refusal quotes the page's own line for the same command. With that, the 7B recorded only the page's commands
105
+ in 3 of 6 tries, and repeated the refused one in the other 3, which is refused again; told only to leave the
106
+ command out, it kept the invented command and dropped the real ones 6 times out of 6.
107
+ - **The final result's commands must come from a finding.** If one doesn't, its sentence (or code-block line) is cut
108
+ and the command is named after the result: "Left out, because no discovery gives them". In earlier runs this
109
+ caught 5 of 119 results, including the 14B's `<venv>/Scripts/activate` and a code block with `pip install
110
+ package_name`. The report warns about such commands, and the suite's honesty table counts them.
111
+ - **Fewer findings recorded from the wrong place.** A finding is refused, with what to do instead, when:
112
+ - it is empty;
113
+ - it copies the page's headings or outline;
114
+ - it describes the page ("this guide covers…") instead of giving its facts;
115
+ - it only asks questions;
116
+ - it repeats the objective or the searches instead of the page;
117
+ - it repeats the checklist's own wording ("covered by [2]").
118
+ - **Cut-off replies are rescued.** A reply cut off inside its parameter is kept for SEARCH, NAVIGATE and READ_MORE.
119
+ It is cut where the words start repeating, and a search is limited to 20 words. A cut-off finding on the results
120
+ page is refused as usual.
121
+ - **Coverage check:**
122
+ - When the model cites only discovery numbers twice, it is asked a yes-or-no question about the cited
123
+ discovery alone, and a "yes" counts only with words copied from it. A "no" still counts when the discovery has
124
+ words that belong to that item alone: the 7B said "no" 3 times out of 3 for "the light-dependent reactions,
125
+ which take place in the thylakoids". The question accepts a partial answer ("answer the item, or part of
126
+ it"); asked whether the discovery "says what the item asks for", the 7B said "no" 6 times out of 6 for that
127
+ same partial answer.
128
+ - Things are counted only when a finding names them.
129
+ - The words that answered each item are shown to the final result, which had said "the discoveries do not
130
+ specify what goes into photosynthesis" over a discovery naming water, sunlight and carbon dioxide.
131
+ - **Final result:**
132
+ - "Not specified …, but <something from the model>" is cut back to the gap.
133
+ - Items whose findings give no amounts are named, so none are supplied.
134
+ - A "My view" paragraph that repeats the result is dropped.
135
+ - Refusal hints no longer quote a sentence where the page describes itself, or a question.
136
+ - The 14B's model calls took longer than the client library's 10-minute default, which ended its runs. The timeout is
137
+ now 30 minutes.
138
+ - A run stopped while its final result was being written says so in the report, and shows the unchecked draft; the
139
+ suite no longer counts it as finished.
140
+
141
+ ### Changed
142
+ - The README says near the top which goals work and which can't yet: anything behind a form, a login or a button,
143
+ such as flight prices. An automated write-up of the project, built from the README, had suggested "the three
144
+ cheapest flights to Denver" as an example goal. The privacy line also says that searches, written from your
145
+ objective, go to DuckDuckGo and pages come from the web; the objective itself, the model and the report stay on your
146
+ computer.
147
+ - Two real reports from the 1.62 suite run, unedited, in `docs/examples/`, with a note on what each got right and
148
+ wrong (a path slip in one; in the other, an opinion that leans on the one part it found nothing about). Linked
149
+ from the README.
150
+ - `llms.txt`, a short plain-text summary for AI tools that read the repository (the convention described at
151
+ llmstxt.org), saying the same as the README: good goals, what it can't do yet, speed, privacy. Nothing in it is
152
+ hidden or addressed to a model as an instruction.
153
+ - A project site (`docs/`, served by GitHub Pages at https://snowfxxx.github.io/LocalAgentBrowser/) with the
154
+ findings, a quick start and the challenge, plus two write-ups of this round: an article, "We Can Do Better: A
155
+ Small AI That Can't Cover Up", and a technical paper, "Verification over Trust". Every regression run so far is
156
+ attached to the release as a zip.
157
+ - Corrected: the README and the regression history had counted the 14B's results that the time limit cut off while
158
+ they were being written. Of its five finishes, two count (2 of 7).
159
+
9
160
  ## [1.62] - 2026-10-25
10
161
  No change in what the agent does: the same prompts, decisions and results as 1.61.
11
162
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: localagentbrowser
3
- Version: 1.62
3
+ Version: 1.64
4
4
  Summary: An autonomous web agent driven by a local LLM (LM Studio) and Playwright. Runs entirely on your own machine.
5
5
  Author: SnowFX
6
6
  License-Expression: MIT
@@ -36,6 +36,7 @@ Dynamic: license-file
36
36
  decides when it's done, all on your own computer.**
37
37
 
38
38
  [![Tests](https://github.com/SnowFXXX/LocalAgentBrowser/actions/workflows/tests.yml/badge.svg)](https://github.com/SnowFXXX/LocalAgentBrowser/actions/workflows/tests.yml)
39
+ [![PyPI](https://img.shields.io/pypi/v/localagentbrowser.svg)](https://pypi.org/project/localagentbrowser/)
39
40
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/LICENSE)
40
41
  ![Python 3.10–3.13](https://img.shields.io/badge/python-3.10%E2%80%933.13-blue.svg)
41
42
  ![Runs locally](https://img.shields.io/badge/LLM-local%20(LM%20Studio)-green.svg)
@@ -48,7 +49,9 @@ A local language model served by [LM Studio](https://lmstudio.ai) decides what t
48
49
  [Playwright](https://playwright.dev/python/) carries it out in a visible Chromium window you can watch. Built
49
50
  and tuned to work well with a **small 7B model on a CPU, no GPU required**.
50
51
 
51
- - 🔒 **No cloud AI and no API keys.** The model runs in your own LM Studio.
52
+ - 🔒 **No cloud AI and no API keys.** The model runs in your own LM Studio. (Its searches, written from your
53
+ objective, go to DuckDuckGo, and it reads pages from the web like any browser; the objective itself, the model and
54
+ the report stay on your computer.)
52
55
  - 🧭 **Goes from objective to findings unattended.** It searches, opens pages, reads long pages part by part,
53
56
  records what's relevant and finishes when the objective is met.
54
57
  - 🛡️ **Keeps a small model on track.** Rules enforced in code stop loops, repeats and drifting, and the model
@@ -56,9 +59,37 @@ and tuned to work well with a **small 7B model on a CPU, no GPU required**.
56
59
  - ⚡ **Built for slow hardware.** It reuses LM Studio's prompt cache, so most turns process only what changed.
57
60
  - 📝 **A readable report every time.** `research_report.md` holds the final result and every finding with its
58
61
  source, written however the run ends; `research_log.txt` keeps every action and reason.
59
- - ✅ **Tested.** 165 tests on Linux and Windows, Python 3.10–3.13, run in a few seconds with no model or browser,
62
+ - ✅ **Tested.** 324 tests on Linux and Windows, Python 3.10–3.13, run in a few seconds with no model or browser,
60
63
  plus a [regression suite](#regression-suite) of live runs on seven different kinds of task.
61
64
 
65
+ **New with 1.64:** parts of the objective no longer drop out of the answer unannounced as often (the coverage check asks for the words first; missing amounts and terms send the agent back), measured on two PCs and then four models with identical code: Qwen2.5-7B 6 of 7, Llama 3.1 8B 7 of 7, Qwen2.5-14B 5 of 7 and Qwen2.5-3B 3 of 7 tasks, with no outside knowledge in any finished result ([regression history](docs/regression-history.md)). On Windows, a launcher with Start-menu and desktop shortcuts opens the report by itself when a run ends.
66
+
67
+ **New with 1.63:** the [project site](https://snowfxxx.github.io/LocalAgentBrowser/), an article,
68
+ [We Can Do Better: A Small AI That Can't Cover Up](https://snowfxxx.github.io/LocalAgentBrowser/article.html), and a
69
+ technical paper, [Verification over Trust](https://snowfxxx.github.io/LocalAgentBrowser/paper.html).
70
+
71
+ ### What it's good for, and what it can't do yet
72
+
73
+ - **Good goals:** questions you would research by reading pages. Examples:
74
+ - a fact ("How tall is Kilimanjaro, in meters and feet?")
75
+ - a list with conditions ("Three free, open-source alternatives to Microsoft Office, and what each is best at")
76
+ - a comparison with a recommendation
77
+ - a how-to
78
+ - an explanation of a topic
79
+ - views from several sources
80
+ - looking something up in official documentation
81
+
82
+ These are the seven kinds of task the [regression suite](#regression-suite) measures.
83
+ - **Not yet:**
84
+ - **Anything behind a form, a login or a button.** It reads pages; it does not click, fill in forms or sign
85
+ in. So goals like "the three cheapest flights to Denver next month" won't work: flight and hotel prices,
86
+ shopping and booking sites need searches it cannot type into.
87
+ - **Fast answers.** On a CPU a run takes about 10 to 45 minutes, and a 7B model sometimes returns thin findings,
88
+ so check the result against its listed sources.
89
+
90
+ See [two example reports](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/docs/examples/README.md), unedited,
91
+ with what each got right and wrong.
92
+
62
93
  📖 **The story behind it:** [Teaching a 7B model on a CPU to finish what it starts](https://dev.to/snowfxxx/teaching-a-7b-model-on-a-cpu-to-finish-what-it-starts-1amc),
63
94
  six lessons from 30 versions of keeping a small local model on track.
64
95
 
@@ -107,6 +138,11 @@ six lessons from 30 versions of keeping a small local model on track.
107
138
  When it finishes, read `research_report.md` in the folder you ran it from. Press Ctrl+C at any time to
108
139
  stop; the report is still written with everything found so far.
109
140
 
141
+ **On Windows**, from a clone of the repository (below), `powershell -ExecutionPolicy Bypass -File
142
+ tools\windows\make_shortcuts.ps1` adds LocalAgentBrowser to the Start menu and the desktop. The launcher checks that
143
+ LM Studio is answering, runs each objective in its own folder under `Documents\LocalAgentBrowser runs`, and opens the
144
+ report as a page in your browser when the run ends.
145
+
110
146
  To work on the code instead, clone the repository and install from it:
111
147
 
112
148
  ```bash
@@ -203,15 +239,15 @@ turns up, so the suite compares versions on all seven at once. 1.54 to 1.56 and
203
239
  measured this way and released with 1.57 and 1.61; [docs/regression-history.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/docs/regression-history.md)
204
240
  has every step's results and what each one showed.
205
241
 
206
- | Task | 1.52 | 1.53 (objective checklist) | 1.57 (coverage check) | 1.61 (verified send-backs, outline pointer) |
207
- |---|---|---|---|---|
208
- | Factual question | Finished, 12 min | Finished, 14 min | Finished, 13 min | Finished, 17 min |
209
- | List of three office suites | Time limit | Finished, 30 min; but WPS Office is not open source | Time limit: three correct open-source suites by turn 7, sent back because no words showed them to be "free" | Finished, 21 min: LibreOffice, WPS Office and OnlyOffice, each marked "not shown in the pages read to be free and open-source" |
210
- | Comparison and recommendation | Time limit | Finished, 39 min | Time limit, after a send-back for "official documentation", which the objective does not ask for | Finished, 26 min, setup and administration from the part of a long page the outline pointer chose |
211
- | How-to (cold brew from 1.55; repotting before) | Time limit | Time limit | Finished, 36 min; but "how long it keeps" answered with the steeping time | Finished, 33 min: every step, the 16-hour steep and the shelf life, cited |
212
- | Explanation (photosynthesis) | Time limit | Finished, 13 min, but thin: no oxygen or water | Finished, 59 min: inputs, outputs and both stages, cited | Finished, 39 min |
213
- | Opinion (owls) | Time limit | Finished, 38 min | Time limit: its first page covered two of the three cultures asked for | Finished, 42 min: four cultures, cited, with a view |
214
- | Documentation (venv, official docs) | Finished, 15 min, from a tutorial site | Time limit (30 min) | Finished, 37 min, all from python.org; but the Windows line repeats the create command instead of the activate one | Time limit: all four items found from python.org, then it read on |
242
+ | Task | 1.52 | 1.53 (objective checklist) | 1.57 (coverage check) | 1.61 (verified send-backs, outline pointer) | 1.64 (quote-first coverage, send-backs for missing amounts and terms) |
243
+ |---|---|---|---|---|---|
244
+ | Factual question | Finished, 12 min | Finished, 14 min | Finished, 13 min | Finished, 17 min | Finished, 17 min |
245
+ | List of three office suites | Time limit | Finished, 30 min; but WPS Office is not open source | Time limit: three correct open-source suites by turn 7, sent back because no words showed them to be "free" | Finished, 21 min: LibreOffice, WPS Office and OnlyOffice, each marked "not shown in the pages read to be free and open-source" | Finished, 34 min: GIMP, Krita and Darktable (the list task asks for Photoshop alternatives from 1.64) |
246
+ | Comparison and recommendation | Time limit | Finished, 39 min | Time limit, after a send-back for "official documentation", which the objective does not ask for | Finished, 26 min, setup and administration from the part of a long page the outline pointer chose | Finished, 49 min |
247
+ | How-to (cold brew from 1.55; repotting before) | Time limit | Time limit | Finished, 36 min; but "how long it keeps" answered with the steeping time | Finished, 33 min: every step, the 16-hour steep and the shelf life, cited | Finished, 50 min |
248
+ | Explanation (photosynthesis) | Time limit | Finished, 13 min, but thin: no oxygen or water | Finished, 59 min: inputs, outputs and both stages, cited | Finished, 39 min | Finished, 73 min, oxygen included |
249
+ | Opinion (owls) | Time limit | Finished, 38 min | Time limit: its first page covered two of the three cultures asked for | Finished, 42 min: four cultures, cited, with a view | Finished, 49 min |
250
+ | Documentation (venv, official docs) | Finished, 15 min, from a tutorial site | Time limit (30 min) | Finished, 37 min, all from python.org; but the Windows line repeats the create command instead of the activate one | Time limit: all four items found from python.org, then it read on | Time limit: read the reference page part after part without recording (finished in 34 and 42 min in the two v11 runs) |
215
251
 
216
252
  ## How it works
217
253
 
@@ -222,7 +258,7 @@ current page, and answers with exactly one JSON action:
222
258
  |---|---|
223
259
  | `SEARCH` | Searches DuckDuckGo (HTML version) and shows a numbered list of results with their real URLs |
224
260
  | `NAVIGATE` | Opens a URL taken from the results or from the current page's links |
225
- | `READ_MORE` | Shows the next part of a long page (pages are read in parts of about 2,500 characters) |
261
+ | `READ_MORE` | Shows the next part of a long page (pages are read in parts of about 2,500 characters), or the unread part whose outline label names an item still missing |
226
262
  | `DISCOVER` | Records information from the current page as a finding |
227
263
  | `FINISH` | Ends the run (after checking each part of the objective is covered); the final result is then written in a separate step |
228
264
 
@@ -272,6 +308,11 @@ The code is in the `localagentbrowser` package, one file per job, each depending
272
308
  its own knowledge when a page says "follow these 6 steps" and the steps come later. The refusal points the way:
273
309
  it quotes the one page sentence closest to what the model wrote, to record instead, or names what the parts
274
310
  shown never mention ("Japan, Navajo"), so the model reads on.
311
+ - **Commands must be on the page, exactly.** Commands and paths in a finding (in backticks, in a code block, or
312
+ any word with a backslash, a `<placeholder>` or two slashes) must appear on the page as written, however often
313
+ the finding is repeated. Word matching cannot catch a wrong command: a 7B recorded `pip install package_name`,
314
+ which the official page never gives, and swapped `bin` and `Scripts` when copying its activation table. The same
315
+ goes for the final result: a command no finding gives is cut and named after the result.
275
316
  - **An objective checklist.** At the start, one short model call splits the objective into a fixed checklist of
276
317
  what the result must contain, keeping conditions like "free, open-source" or "three". Each finding names the
277
318
  items it serves, the checklist with its findings is in every prompt, and every check goes through these items
@@ -283,8 +324,10 @@ The code is in the `localagentbrowser` package, one file per job, each depending
283
324
  its own, and the code checks the verdict instead of taking it on trust: an item nothing was copied for, fewer
284
325
  things than asked for ("only 1 of 3 found"), and things not shown, in words copied from a finding about them,
285
326
  to meet a condition such as "open-source". A claim that something is missing is dropped when every word of it is
286
- already in the findings. With gaps, the FINISH is sent back once, with the next step named ("SEARCH for
287
- 'OnlyOffice free and open-source' to check it, or replace it"), and the next turn starts from a fresh prompt.
327
+ already in the findings. Only gaps the code verifies send the FINISH back, once: an item nothing was copied for,
328
+ fewer things than asked for ("only 1 of 3 found"), or nothing recorded. The model's other verdicts, and things
329
+ not shown to meet a condition, only shape the final result. The send-back names the next step, and the next turn
330
+ starts from a fresh prompt.
288
331
  - **Numbered findings.** Findings are numbered in the prompt and listed with every check, and the model names
289
332
  the finding that covers each part of the objective ("covered by [2]") instead of just saying "covered".
290
333
  - **Knowing when it's done.** After every new finding the model is asked whether the objective is now fully
@@ -299,9 +342,10 @@ The code is in the `localagentbrowser` package, one file per job, each depending
299
342
  cite findings by number, give as many items as asked for (never repeating one, and saying how many were not
300
343
  found), and add a "My view:" paragraph only when the objective asks for an opinion. A small model writes far
301
344
  better when that is its only job, and every claim stays traceable to a recorded finding. What no finding
302
- answers is not left to the model: those checklist items, and things not shown to meet a condition, are left out
303
- of what it is asked to write, and the code adds them after the result as "Not found in the pages read" and
304
- "Left out, not shown to meet the conditions". The report flags any number in the final result that appears in
345
+ answers is not left to the model: those checklist items are left out of what it is asked to write, and the code
346
+ adds them after the result as "Not found in the pages read". A thing not shown to meet a condition stays in the
347
+ result, and the code marks it where it is first named ("not shown in the pages read to be open-source"), or lists
348
+ it after the result if the result does not name it. The report flags any number in the final result that appears in
305
349
  none of the findings, the most harmful kind of slip in a how-to.
306
350
  - **Error pages are recognised.** A page answering 404, 403 and so on counts as a failed visit, not content.
307
351
  - **Readable pages.** Navigation menus, footers, cookie banners and site notices such as fundraising banners are
@@ -356,13 +400,32 @@ It was developed and tested with Qwen2.5-7B-Instruct (Q4_K_M). Any instruction-t
356
400
  serves should work, as long as the server supports `response_format` with a JSON schema (LM Studio 0.3 and
357
401
  later). Set `LMSTUDIO_MODEL` and `LMSTUDIO_CONTEXT_LENGTH` to match. Reports with other models are very welcome.
358
402
 
403
+ The full suite, run on four models with the same code, 90 minutes per task, CPU only (October 2026):
404
+
405
+ | Model | Tasks finished | Model time | Gaps filled from the model's own knowledge |
406
+ |---|---|---|---|
407
+ | Qwen2.5-7B-Instruct | 6 of 7 | 197 min | 0 |
408
+ | Qwen2.5-14B-Instruct | 2 of 7 | 535 min | 0 |
409
+ | Llama-3.1-8B-Instruct | 2 of 7 | 278 min | 0 |
410
+ | Qwen2.5-3B-Instruct | 0 of 7 | 302 min | — |
411
+
412
+ Where they finished, every model's results were honest by the suite's measures. What separates them is speed and
413
+ follow-through:
414
+ - The 14B was about 2.5 times slower than the 7B on a CPU. It reached FINISH on five tasks, but on three of them
415
+ the time limit hit while the final result was being written, so only two count.
416
+ - Llama found most items but rarely finished in time.
417
+ - The 3B recorded findings on every task but never finished one.
418
+
419
+ With no time limit, the 7B finished 7 of 7 (277 minutes). These measures are word checks: the suite counted a
420
+ documentation result with an invented command as clean, which led to the command check above.
421
+
359
422
  **Can I use another OpenAI-compatible server instead of LM Studio?**
360
423
  Probably: point `LMSTUDIO_BASE_URL` at it. It has only been tested with LM Studio, and the speed tricks rely
361
424
  on the server reusing cached prompt prefixes (llama.cpp-based servers do).
362
425
 
363
426
  **Is anything sent to the internet?**
364
427
  No AI service is involved, and nothing about your run is uploaded. The agent does browse the real web,
365
- though: search queries go to DuckDuckGo, and pages it opens load normally, as if you visited them yourself.
428
+ though: search queries, written from your objective, go to DuckDuckGo, and pages it opens load normally, as if you visited them yourself.
366
429
 
367
430
  **Where are the results?**
368
431
  In the folder you ran it from: `research_report.md` has the final result and every finding with its source,
@@ -400,7 +463,8 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
400
463
  - **Very strict objectives.** An objective that forbids finishing until everything is "fully validated" used
401
464
  to keep the agent looking for something the web may not contain. On 1.50 it finished such an objective in 25
402
465
  minutes, but with thin findings and without naming what it could not find, so check the result against the
403
- objective.
466
+ objective. Since 1.57 the code lists checklist items no finding answers after the result; this has not been
467
+ tested on a strict objective yet.
404
468
  - **Check the citations.** The final result is told to use only recorded findings, but a 7B model sometimes
405
469
  puts the wrong number on a citation, adds a line no finding supports, leaves out a step or misreads a part of
406
470
  the question (on 1.57 it answered "how long it keeps in the fridge" with the steeping time), so verify a claim
@@ -418,7 +482,7 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
418
482
  - [x] Write the final result in a separate, rule-bound step and flag unsupported numbers (1.32–1.38)
419
483
  - [x] Finish as soon as the objective is covered (1.35)
420
484
  - [x] Get the model to weigh each part of a long page before reading on (1.42)
421
- - [ ] Let very strict objectives end with the gaps named instead of searching indefinitely (they finish since 1.50; naming the gaps is still open)
485
+ - [ ] Let very strict objectives end with the gaps named instead of searching indefinitely (they finish since 1.50; since 1.57 the code names checklist items no finding answers, not yet tested on a strict objective)
422
486
  - [x] Measure every change on a regression suite of seven kinds of task (1.53)
423
487
  - [x] Keep a fixed checklist of the objective's parts instead of re-splitting it at every check (1.53)
424
488
  - [ ] Check that a finding really covers its checklist item, including conditions like "open source" (partly, since
@@ -430,8 +494,13 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
430
494
  - [ ] Rewind dead ends: save the conversation before an expensive step such as reading a long page, and if it
431
495
  leads nowhere, return to that point with a short note instead of carrying the unused page text in every later
432
496
  prompt (LM Studio reuses its cache up to the saved point)
497
+ - [ ] Catch an objective too ambiguous to research before the run starts, and only then ask one question: never
498
+ during a run, and only for extreme ambiguity, so the run can still be left unattended but isn't spent chasing an
499
+ objective it can't pin down
500
+ - [ ] A small project site on GitHub Pages: the README's essentials, the example reports and `llms.txt` at the
501
+ site's root, where AI tools look for it
433
502
  - [ ] Try more kinds of objectives (seven so far) and adjust the rules that don't generalise
434
- - [ ] Make fresh prompts (the slowest kind of turn) cheaper still (31% cheaper since 1.34)
503
+ - [ ] Make fresh prompts (the slowest kind of turn) cheaper still (31% cheaper since 1.34; about 2,500 tokens since 1.61, from 3,500–4,900)
435
504
  - [ ] Interacting with pages (clicking, forms) for tasks beyond reading
436
505
 
437
506
  Ideas and requests are welcome in [issues](https://github.com/SnowFXXX/LocalAgentBrowser/issues).
@@ -466,6 +535,10 @@ To measure a change on all seven kinds of task (about four hours on a CPU), comp
466
535
  python tools/regression.py --baseline regression_runs/<earlier run>/summary.json
467
536
  ```
468
537
 
538
+ To measure another model on the same tasks, name it as LM Studio lists it, for example
539
+ `--model meta-llama-3.1-8b-instruct`. The model is loaded before the first task and its context length checked, so
540
+ every run is measured with the same context length; the run's folder and summary name the model.
541
+
469
542
  Each run gets a folder in `regression_runs/` with every task's report, journal, console output and prompt
470
543
  trace, and a `summary.md` that is updated after each task: whether it finished, turns, model time, how many
471
544
  checklist items got findings, which checks fired, and problems found by simple word checks (missing answers,