Files
autocomplete-model/daemon
HarvmasterandClaude Opus 5.5 87d3c3c3bf
ci / build (push) Canceled after 0s
Extension 0.6.0: next-edit, token healing, TS errors context, cursor-move, prewarm
- shared/nextedit.ts: next-edit prompt format (region rewrite or NO_EDIT, Qwen spare special tokens)
- shared/diagnostics.ts: TS errors near the cursor as context; symbols format 2 adds namespace imports
- shared/prompt.ts: token healing (cut the half-typed word, force it via grammar), errors header section
- daemon: model profiles carry contextFormat/errors/members/nextEdit; /v1/next-edit with edit-burst
  tracking; /v1/prewarm; /v1/debug/last; token healing on by default
- extension: next-edit decorations (Tab apply / Esc dismiss), suggest on cursor move, prewarm on focus,
  Show Last Prompt, update check against releases, diagnostics in the edit recorder
- models/README: training-data attribution; release script profiles for stage-d/stage-e
- .gitea/workflows/ci.yml: build + test, publish release on vscode-v* tags (needs a runner + RELEASE_TOKEN)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J39imRDT8L7xYbWzsVWd8A
2026-10-03 17:21:38 +00:00
..

acd: local completion daemon

Builds fill-in-the-middle prompts in exactly the format the models were trained on (it shares ../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.

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 on Linux).

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 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