hkblockchaintechnology commited on
Commit
918bce6
Β·
verified Β·
1 Parent(s): 3fcc46c

Update project card from marimo

Browse files
Files changed (1) hide show
  1. README.md +97 -21
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 β€” the model is small enough to run on the
22
- same machine it is controlling.
23
 
24
- > **Status: project scaffold.** This card pins down the harness contract
25
- > (observe β†’ think β†’ act β†’ verify), the intended layout, and the safety model.
26
- > Implementation lands next; see the [roadmap](#-roadmap).
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
- ## Intended layout
73
 
74
  ```
75
  tiny-computer-agent/
76
  β”œβ”€β”€ README.md
77
- β”œβ”€β”€ tiny_computer_agent.py # marimo notebook: drive / watch the loop
78
- β”œβ”€β”€ src/tiny_computer_agent/
79
- β”‚ β”œβ”€β”€ observe.py # screen capture + OCR / accessibility tree
80
- β”‚ β”œβ”€β”€ brain.py # model backends behind one interface
81
- β”‚ β”œβ”€β”€ act.py # action vocabulary + pyautogui / xdotool executor
82
- β”‚ β”œβ”€β”€ loop.py # observe β†’ think β†’ act β†’ verify
83
- β”‚ └── safety.py # dry-run, allow/deny lists, kill switch, step budget
84
- └── LICENSE
 
 
 
 
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
- - `--dry-run` logs every action without executing it, so you can read the plan first.
91
  - Deny-list for shells, terminals, payment flows and password managers.
92
- - A step budget plus a global hotkey kill switch before anything touches the pointer.
93
  - **Local-first, for real:** screen pixels and keystrokes never leave the machine.
94
 
95
  ## Roadmap
96
 
97
- - [ ] `loop.py` + `act.py` with the mock brain β€” the harness is testable before any model download
98
- - [ ] OCR / AT-SPI element index, and click-by-element instead of click-by-pixel
99
- - [ ] tiny-VLM grounding backend (transformers + llama.cpp GGUF)
100
- - [ ] marimo UI: live screen preview, action log, pause / resume / step
101
- - [ ] append-only run traces, so failed episodes can be replayed and scored
 
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