feat: add llama.cpp adapter and persistent desktop tool loop

This commit is contained in:
Zoe
2026-09-19 15:06:13 -05:00
parent 118a5387cb
commit 1a4e4d0a97
8 changed files with 332 additions and 6 deletions
+24 -4
View File
@@ -1,6 +1,6 @@
# Desktop harness — first slice
Manual SSH and X11 controls. There is **no model loop, persistent conversation, scheduler, or Jev integration yet**. The package name is a placeholder.
SSH and X11 controls plus a bounded llama.cpp tool loop. Conversations and tool operations are recorded in SQLite. Sleep/wake, automatic resumption, and Jev integration are not implemented. The package name is a placeholder.
## On berlin (or your development computer)
@@ -109,8 +109,28 @@ npm run setup:check
`.env.example` contains berlin's llama.cpp origin and model ID. Edit `.env` for your installation. The origin excludes `/v1`; future model requests will append the API path. `DATABASE_PATH` defaults to `./data/token.sqlite`, relative to the process working directory. `.env` and database files are ignored by Git. The check validates configuration and opens/checks SQLite; it does not contact the model or operate the desktop.
`src/database.ts` exports a general `openDatabase()` connection using Node's built-in SQLite, with foreign keys, WAL, and a five-second busy timeout. The caller owns the connection and must close it. Use one connection in the eventual supervisor and pass it to domain modules; it is not tied to conversations or logs. Append numbered SQL migrations to `migrations` as actual schemas are introduced (projects, schedules, messages, etc.). Applied migration SQL is recorded and checked against subsequent builds. Pending migrations run transactionally; incompatible history fails rather than silently changing existing data. There is intentionally no speculative domain schema or ORM yet. Back up live databases using a SQLite-aware backup mechanism, not by copying only the main file while WAL is active.
`src/database.ts` exports a general `openDatabase()` connection using Node's built-in SQLite, with foreign keys, WAL, and a five-second busy timeout. The caller owns the connection and must close it. Use one connection in the eventual supervisor and pass it to domain modules; it is not tied to conversations or logs. Append numbered SQL migrations to `migrations` as actual schemas are introduced (projects, schedules, messages, etc.). Applied migration SQL is recorded and checked against subsequent builds. Pending migrations run transactionally; incompatible history fails rather than silently changing existing data. The first migration stores commissioning runs, conversation messages, and tool operations. Other domains can add independent tables through subsequent migrations; there is no ORM. Back up live databases using a SQLite-aware backup mechanism, not by copying only the main file while WAL is active.
## Next milestone
## Model connection and editor test
Once capture, Unicode insertion, key combinations, and shell timeout work on the real VM, add the llama.cpp adapter, durable tool-call records, and a single model/tool loop. Wake/sleep and restart recovery follow. No SSH connection or real graphical session is available in the development sandbox, so those checks must be run on your setup.
```sh
npm install
npm run build
npm run agent -- probe home
```
The probe captures the desktop, sends the screenshot to llama.cpp, and requests a description and a proposed capture tool call. It prints but **does not execute** the proposed calls. Check that the description matches the screen and the call is `desktop` with empty `actions`. This tests the actual vision and tool-call message format.
Then, with the desktop unlocked and no unsaved work in the editor:
```sh
npm run agent -- run home 'Use the desktop to open Mousepad, type a short greeting, and save it as /home/user/harness-test.txt. Use shell to read that file and verify its contents, then stop. Do not modify any other existing files.' 8
```
`run` really executes model-generated desktop actions and arbitrary shell commands with the VM user's permissions. Watch the first runs. Do not manually interact with the desktop concurrently. The optional turn limit defaults to 8, maximum 30; each turn permits at most eight sequential tool calls. Ctrl+C stops inference or waits for the current tool to finish before stopping. It does not undo effects. There is no interactive pause/resume yet.
Runs, messages, and operation results are stored in SQLite. Screenshots live alongside the database under `artifacts/<run-id>/`; the latest screenshot is sent to the model, while older ones remain on disk. Reasoning returned by the endpoint is retained as part of its assistant message. Only the commissioning instructions are used—no identity prompt or resident history is introduced.
A final response without calls ends the run. Truncated model responses are rejected without executing their calls. Connection or desktop errors can leave partial effects; tool errors explicitly tell the model not to assume otherwise. If the supervisor is killed, operations left as `started` have unknown outcomes. Runs are not automatically resumed or retried: inspect them before starting another test. A new invocation creates a new conversation. A turn bound limits these initial sessions; token-budget enforcement and long-term context management remain future work.
The development environment cannot currently resolve berlin, so end-to-end model and desktop testing must be done from your machine. Next: persistent sleep/wake and deliberate restart recovery.