Update project card from marimo
Browse files
README.md
CHANGED
|
@@ -18,12 +18,12 @@ tags:
|
|
| 18 |
# π±οΈ Tiny Computer Agent
|
| 19 |
|
| 20 |
**An agentic harness that drives a real computer with a tiny, fully local model.**
|
| 21 |
-
No cloud API, no API keys, no telemetry β
|
| 22 |
-
|
| 23 |
|
| 24 |
-
> **Status:
|
| 25 |
-
>
|
| 26 |
-
>
|
| 27 |
|
| 28 |
## The idea, in one loop
|
| 29 |
|
|
@@ -46,6 +46,77 @@ same machine it is controlling.
|
|
| 46 |
4. **Verify** β the next frame shows whether it worked. Repeat, bounded by a step
|
| 47 |
budget and a kill switch.
|
| 48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
## Why "tiny" is the whole point
|
| 50 |
|
| 51 |
The harness does the heavy lifting, so the model does not have to be clever:
|
|
@@ -69,36 +140,41 @@ Pluggable behind one interface; nothing here needs a network call at run time.
|
|
| 69 |
- **OCR + text-only planner** β no VLM at all; the cheapest credible baseline
|
| 70 |
- **mock brain** β deterministic scripted actions, used to test the harness itself
|
| 71 |
|
| 72 |
-
##
|
| 73 |
|
| 74 |
```
|
| 75 |
tiny-computer-agent/
|
| 76 |
βββ README.md
|
| 77 |
-
βββ
|
| 78 |
-
βββ
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
β βββ
|
| 82 |
-
β βββ
|
| 83 |
-
β
|
| 84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
```
|
| 86 |
|
| 87 |
## Safety, because this thing has your mouse
|
| 88 |
|
| 89 |
- Run it in a **VM, container, or throwaway desktop account** β not your real session.
|
| 90 |
-
-
|
| 91 |
- Deny-list for shells, terminals, payment flows and password managers.
|
| 92 |
-
- A step budget plus a
|
| 93 |
- **Local-first, for real:** screen pixels and keystrokes never leave the machine.
|
| 94 |
|
| 95 |
## Roadmap
|
| 96 |
|
| 97 |
-
- [
|
| 98 |
-
- [
|
| 99 |
-
- [ ]
|
| 100 |
-
- [ ]
|
| 101 |
-
- [ ]
|
|
|
|
| 102 |
|
| 103 |
## License
|
| 104 |
|
|
|
|
| 18 |
# π±οΈ Tiny Computer Agent
|
| 19 |
|
| 20 |
**An agentic harness that drives a real computer with a tiny, fully local model.**
|
| 21 |
+
No cloud API, no API keys, no telemetry β and a core that imports nothing outside
|
| 22 |
+
the Python standard library.
|
| 23 |
|
| 24 |
+
> **Status: early alpha.** The loop runs end to end today, with a scripted screen,
|
| 25 |
+
> dry-run execution, a CLI and 56 offline tests. The vision backend is a
|
| 26 |
+
> documented seam, not a feature β see [what works](#-what-works-today).
|
| 27 |
|
| 28 |
## The idea, in one loop
|
| 29 |
|
|
|
|
| 46 |
4. **Verify** β the next frame shows whether it worked. Repeat, bounded by a step
|
| 47 |
budget and a kill switch.
|
| 48 |
|
| 49 |
+
## What works today
|
| 50 |
+
|
| 51 |
+
```
|
| 52 |
+
$ python -m tiny_computer_agent
|
| 53 |
+
goal: click 'Save' to save the document
|
| 54 |
+
mode: dry-run | screen: scripted demo | kill switch: create /tmp/tiny-computer-agent.STOP to stop
|
| 55 |
+
|
| 56 |
+
step 0 | wait seconds=0.5 reason="'Save' is not on screen yet" | ok: (dry-run) would wait 0.5s
|
| 57 |
+
step 1 | click label='Save' reason="matched 'Save' in the element index" | ok: (dry-run) would click -> pixel (360, 132)
|
| 58 |
+
step 2 | done reason="already clicked 'Save'; goal assumed met" | ok: goal reported met
|
| 59 |
+
|
| 60 |
+
result: success - brain reported done: already clicked 'Save'; goal assumed met
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
Shipped and tested:
|
| 64 |
+
|
| 65 |
+
- **the loop** β `AgentLoop` runs observe β think β act β verify, **re-reads the
|
| 66 |
+
screen after every action**, and stops on done, on a step budget, on the kill
|
| 67 |
+
switch, on a policy refusal, on a failed action, or on a brain error. Every step
|
| 68 |
+
is recorded in an `Episode` you can render or turn into rows.
|
| 69 |
+
- **a closed action vocabulary** β `click` `type` `key` `scroll` `wait` `done`,
|
| 70 |
+
validated *before* anything executes. A model that invents a verb gets a recorded
|
| 71 |
+
error, not a click.
|
| 72 |
+
- **three brains** β `MockBrain` replays a script; `PlannerBrain` is rule-based and
|
| 73 |
+
genuinely clicks the element matching the goal (it waits for a dialog instead of
|
| 74 |
+
flailing, and refuses to click the same label twice); `VLMBrain` is the seam β
|
| 75 |
+
prompt assembly and reply validation are done, `_generate()` is yours.
|
| 76 |
+
- **two executors** β `DryRunExecutor` is the default: it logs the plan and resolves
|
| 77 |
+
every label to a pixel. `PyAutoGuiExecutor` does real input and **refuses to click
|
| 78 |
+
when a label matches no element**, because a tiny model guessing pixels is how you
|
| 79 |
+
click "Delete account". Dry-run fails exactly where live input refuses, so a
|
| 80 |
+
rehearsal never gives false confidence.
|
| 81 |
+
- **policy gates** β deny-listed text (`sudo`, `rm -rf`, "password", "api_key"),
|
| 82 |
+
deny-listed widgets (terminal, keychain, password manager, wallet, bank), four
|
| 83 |
+
deny-listed key chords, a kill-switch file checked before every action, and a step
|
| 84 |
+
budget.
|
| 85 |
+
- **real input needs two deliberate flags** β `--real-input` *and*
|
| 86 |
+
`TINY_COMPUTER_AGENT_ALLOW_REAL_INPUT=1`. Default is a dry run.
|
| 87 |
+
- **56 tests** needing no display, no model and no network.
|
| 88 |
+
|
| 89 |
+
What does **not** work yet: seeing a real screen *usefully*. `GrabScreen` captures
|
| 90 |
+
pixels through `mss`, but nothing yet turns pixels into an element index (OCR or
|
| 91 |
+
AT-SPI), so a live screen currently yields zero elements β which is exactly what the
|
| 92 |
+
label path depends on. And no model is wired up.
|
| 93 |
+
|
| 94 |
+
## Install and run
|
| 95 |
+
|
| 96 |
+
```bash
|
| 97 |
+
pip install -e . # core: standard library only, no deps
|
| 98 |
+
pytest # 56 offline tests
|
| 99 |
+
python -m tiny_computer_agent # scripted demo, dry run
|
| 100 |
+
python -m tiny_computer_agent --live # your real screen, still dry run
|
| 101 |
+
```
|
| 102 |
+
|
| 103 |
+
## Put it on your own task
|
| 104 |
+
|
| 105 |
+
```python
|
| 106 |
+
from tiny_computer_agent import AgentLoop, Element, FakeScreen, MockBrain
|
| 107 |
+
|
| 108 |
+
screen = FakeScreen([(Element("Save", x=320, y=120, width=80, height=24),)])
|
| 109 |
+
brain = MockBrain([{"kind": "click", "label": "Save"},
|
| 110 |
+
{"kind": "done", "reason": "saved"}])
|
| 111 |
+
|
| 112 |
+
episode = AgentLoop(screen=screen, brain=brain).run("save the document")
|
| 113 |
+
print(episode.render())
|
| 114 |
+
episode.to_rows() # rows for a dataframe or notebook table
|
| 115 |
+
```
|
| 116 |
+
|
| 117 |
+
Swap `FakeScreen` for `GrabScreen()` and `MockBrain` for your `VLMBrain` subclass and
|
| 118 |
+
that is the whole distance between the tests and a live agent.
|
| 119 |
+
|
| 120 |
## Why "tiny" is the whole point
|
| 121 |
|
| 122 |
The harness does the heavy lifting, so the model does not have to be clever:
|
|
|
|
| 140 |
- **OCR + text-only planner** β no VLM at all; the cheapest credible baseline
|
| 141 |
- **mock brain** β deterministic scripted actions, used to test the harness itself
|
| 142 |
|
| 143 |
+
## Layout
|
| 144 |
|
| 145 |
```
|
| 146 |
tiny-computer-agent/
|
| 147 |
βββ README.md
|
| 148 |
+
βββ LICENSE
|
| 149 |
+
βββ pyproject.toml
|
| 150 |
+
βββ tiny_computer_agent_app.py # marimo console: run an episode, publish this card
|
| 151 |
+
βββ tiny_computer_agent/
|
| 152 |
+
β βββ actions.py # the closed action vocabulary
|
| 153 |
+
β βββ observe.py # Observation + element index; FakeScreen, GrabScreen
|
| 154 |
+
β βββ brain.py # MockBrain, PlannerBrain, VLMBrain (the seam)
|
| 155 |
+
β βββ act.py # DryRunExecutor (default) + PyAutoGuiExecutor
|
| 156 |
+
β βββ safety.py # Policy: deny lists, kill switch, step budget
|
| 157 |
+
β βββ loop.py # AgentLoop, Episode, Step
|
| 158 |
+
β βββ __main__.py # CLI
|
| 159 |
+
βββ tests/ # 56 tests: no display, no model, no network
|
| 160 |
```
|
| 161 |
|
| 162 |
## Safety, because this thing has your mouse
|
| 163 |
|
| 164 |
- Run it in a **VM, container, or throwaway desktop account** β not your real session.
|
| 165 |
+
- Dry run is the default; read the whole plan before letting it near your pointer.
|
| 166 |
- Deny-list for shells, terminals, payment flows and password managers.
|
| 167 |
+
- A step budget plus a kill-switch file checked before every action.
|
| 168 |
- **Local-first, for real:** screen pixels and keystrokes never leave the machine.
|
| 169 |
|
| 170 |
## Roadmap
|
| 171 |
|
| 172 |
+
- [x] `loop.py` + `act.py` with the mock brain β the harness is testable before any model download
|
| 173 |
+
- [x] policy gates: deny lists, kill switch, step budget, dry run by default
|
| 174 |
+
- [ ] OCR / AT-SPI element index, so a live screen has clickable labels
|
| 175 |
+
- [ ] tiny-VLM grounding backend, behind `VLMBrain._generate()`
|
| 176 |
+
- [ ] marimo console: live screen preview, action log, pause / resume / step
|
| 177 |
+
- [ ] persist episodes, so failed runs can be replayed and scored
|
| 178 |
|
| 179 |
## License
|
| 180 |
|