Restructure into a monorepo: models, VS Code extension, daemon, shared

- models/: GGUFs (Git LFS), manifest.json, model card, Apache-2.0 LICENSE + NOTICE
- extensions/vscode/: the Local Autocomplete extension (v0.5.0, publisher harvmaster)
- daemon/: acd completion daemon (bundled into the extension; also runs standalone)
- shared/: prompt layout + symbol extraction shared with the training pipeline
- scripts/: make-model-release.mjs, publish-extension-release.mjs (Gitea releases)
- README with quick start, settings, architecture, build and release instructions;
  MIT license for code; CHANGELOG

The default model manifest URL moves to models/manifest.json.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 15:37:19 +00:00
co-authored by Claude Opus 5.5
parent f8dcf1b7df
commit fa8f775779
52 changed files with 309630 additions and 207 deletions
+54
View File
@@ -0,0 +1,54 @@
# acd: local completion daemon
Builds fill-in-the-middle prompts in exactly the format the models were trained on (it shares
[`../shared/`](../shared) with the training pipeline) and serves completions through a llama-server it manages.
Editors talk to it over localhost HTTP. Design notes: [../docs/architecture.md](../docs/architecture.md).
**You usually don't run this yourself:** the VS Code extension bundles it and runs it in *managed mode*. Run it
standalone for external mode, for other editors, or when developing.
## Running standalone
Requires Node ≥ 22.18 (runs TypeScript directly) and a `llama-server` binary (`brew install llama.cpp` on macOS,
or a [llama.cpp release](https://github.com/ggml-org/llama.cpp/releases) on Linux).
```sh
npm install
npm start # node src/main.ts --config acd.config.json
node src/acctl.ts status # or: mode simple|symbols|raw · model <name> · on · off
npm run smoke # end-to-end test (needs the models from ../models, via Git LFS)
```
`acd.config.json` uses `llama-server` from your PATH with `-ngl 99` (Apple GPU), and the models in `../models`.
- **Linux / CPU:** copy it to `acd.config.local.json` (git-ignored), set `"binary"` to your llama-server and `"args": ["-t", "<physical cores>"]`, then run `node src/main.ts --config acd.config.local.json`.
- **Serving another machine** (e.g. an M1 Max serving a laptop): set `"host": "0.0.0.0"` and point the editor's `serverUrl` at it, using `daemon.mode: "external"`. There's no auth, so only do this on a trusted network.
- **Start on login:** [`acd.service`](acd.service) is a systemd user unit.
## Context modes
| mode | prompt | models |
|---|---|---|
| `symbols` | repo header + language-service symbols (imports' signatures, repo-local types), from `../shared/symbols.ts`, the same code that built the training data. Requires the editor to send `workspaceRoot`; otherwise the request runs as `simple`. | stage-c |
| `simple` | repo name + file path header | stage-c |
| `raw` | plain suffix-first FIM | stage-b (spm), base-0.5b (psm) |
The mode and model are global to the daemon and persisted in `acd.state.json`. VS Code, Zed and `acctl` all see the same toggle.
**How symbols mode stays fast:**
- Context is built in a worker thread (one TypeScript language service per workspace) and cached per *anchor*: the file, the enclosing top-level declaration and the import block. While you type inside one function the header is identical and the KV cache keeps hitting; the smoke test shows the same ~2 re-processed tokens per keystroke as `simple`.
- When the anchor changes, the daemon waits up to `symbols.waitMs` for fresh context, else uses the file's previous context (stale-while-revalidate).
- Member completions after `.` are off (`symbols.members`): every `.` would change the header and force a cold prefill.
**`this.` repair** (`thisRepair.enabled`, any mode, needs `workspaceRoot`): when the identifier you're typing only resolves as a member of the enclosing class, the daemon completes as if `this.` were there. It returns `replaceBefore` + `filterText` so the editor replaces `getU` with `this.getUser(id)`.
**Edit recordings:** `POST /v1/edits` appends opted-in editor edit events to `recording.dir` (default `recordings/`, git-ignored). These are the future training data for next-edit prediction.
## API
- `POST /v1/fim`: `{ requestId?, repo, path, languageId?, prefix, suffix, prefixLineOffset?, mode?, singleLine?, maxLines? }` returns `{ text, mode, singleLine, timings, … }`. A newer request cancels the in-flight one; closing the connection cancels too.
- `GET|PUT /v1/config`: `{ enabled, model, mode }`. Changing the model restarts llama-server.
- `POST /v1/feedback`: editor events, written to the local log only when `telemetry.enabled`.
- `POST /v1/edits`: `{ events }` from editors that opted in to edit recording.
- The `/v1/fim` request may include `workspaceRoot` (absolute path on the daemon's machine). Responses may include `replaceBefore` / `filterText` (the `this.` repair) and `symbols: { status: hit|fresh|stale|none, items }`.
- `GET /health`