https://github.com/dcai/copilot-lsp-client-demo
https://github.com/dcai/copilot-lsp-client-demo
Last synced: 7 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/dcai/copilot-lsp-client-demo
- Owner: dcai
- Created: 2026-04-13T09:00:24.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-06-02T02:54:18.000Z (16 days ago)
- Last Synced: 2026-06-02T04:14:31.676Z (16 days ago)
- Language: TypeScript
- Size: 77.1 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
# copilot-lsp-stats
Tiny CLI harness for testing `@github/copilot-language-server` against a TypeScript file.
It does three useful things:
- starts the Copilot language server over stdio
- reports the editor as `neovim`
- lets you authenticate and request inline completions from the CLI
## Requirements
- Bun
- Node.js `>= 20.8`
- A GitHub account with Copilot access
## Install
```bash
bun install
```
Normal usage does not require a build step. Bun runs the TypeScript CLI directly.
Optional typecheck:
```bash
bun run typecheck
```
## Commands
### Run random completion tests
```bash
./scripts/run-random-completions.sh 10
```
This script now uses Bun under the hood, so no prebuild is needed.
What it does:
- takes one numeric argument for run count
- randomly picks one fixture each run
- uses weighted selection:
- 80% TypeScript
- 10% Markdown
- 5% Bash
- 5% YAML
- sends the completion request for each run
- sends acceptance telemetry for about 90% of runs
Current fixture map:
- `fixtures/sample.ts`
- `fixtures/sample.md`
- `fixtures/sample.sh`
- `fixtures/sample.yaml`
### Generate random files with Copilot
```bash
./scripts/void-run.sh
```
What it does:
- picks one output format using weighted selection
- asks Copilot to generate more lines than needed
- runs Copilot from an isolated temporary working directory
- disables repo and user custom instruction files with `--no-custom-instructions`
- asks Copilot to write the generated content directly into `void/`
- checks that the written file has at least `TARGET_LINES` lines
- prints the temp work dir, `tree`, `head`, and `tail` for a quick visual check
- writes debug output to `void/void-run-debug.log`
Current format weights:
- 45% TypeScript
- 10% JavaScript
- 10% Python
- 10% Markdown
- 10% Lua
- 8% JSON
- 7% YAML
Environment variables:
- `TARGET_LINES` controls how many lines are required and saved
- `PROMPT_MIN_LINES` controls how many lines the prompt asks Copilot to generate
Examples:
```bash
./scripts/void-run.sh
TARGET_LINES=150 ./scripts/void-run.sh
TARGET_LINES=150 PROMPT_MIN_LINES=180 ./scripts/void-run.sh
```
### Check status
```bash
bun run auth:status
```
### Sign in
```bash
bun run auth:signin
```
What happens:
1. the CLI starts the language server
2. it sends `signIn`
3. the server returns a `userCode`
4. the CLI executes the follow-up command returned by the server
5. the browser should open to GitHub auth
6. once auth finishes, the server should emit a new status
If the browser does not open automatically, copy the `verificationUri` and `userCode` from the printed response and finish the flow manually.
### Sign out
```bash
bun run auth:signout
```
### Request a completion for a TypeScript file
```bash
bun run complete --file fixtures/sample.ts --line 7 --character 2
```
Notes:
- `line` and `character` are **zero-based**
- the file is opened as a TypeScript document
- the client sends `textDocument/didShowCompletion` for the first result
- add `--accept-first` to always accept the first suggestion
- add `--accept-rate <0-100>` to accept the first suggestion at a percentage rate
## Good test example
The sample TypeScript file contains this function:
```ts
export const printGreeting = (name: string): void => {
const greeting = buildGreeting(name);
};
```
The most useful test is to ask for a completion on the blank line after `greeting`.
Run:
```bash
bun run complete --file fixtures/sample.ts --line 8 --character 2
```
You should get a response with an `items` array. A likely suggestion would be something like:
```ts
console.log(greeting);
```
If you want to simulate the user accepting the first suggestion too:
```bash
bun run complete --file fixtures/sample.ts --line 8 --character 2 --accept-first
```
If you want a partial acceptance rate instead:
```bash
bun run complete --file fixtures/sample.ts --line 8 --character 2 --accept-rate 90
```
That will:
- request inline completions
- mark the first one as shown
- call `workspace/executeCommand` for the first completion item when the acceptance check passes
## What the CLI sends
### Editor identity
The client identifies itself during `initialize` as:
```json
{
"editorInfo": {
"name": "neovim",
"version": "0.12.1"
}
}
```
You can override the version:
```bash
bun run complete --file fixtures/sample.ts --line 8 --character 2 --editor-version 0.11.0
```
### LSP flow used by the CLI
For completion testing, the client does this:
1. `initialize`
2. `initialized`
3. `workspace/didChangeConfiguration`
4. `textDocument/didOpen`
5. `textDocument/didFocus`
6. `textDocument/inlineCompletion`
## Raw logs
This CLI prints raw client/server JSON-RPC messages to stdout so you can inspect exactly what happened.
That means it is ugly on purpose. Like a wrench. A beautiful, violent wrench.
## Caveats
- auth success can take a few seconds after the browser flow finishes
- the CLI does not patch the file on disk; it only asks the server for completions
- there is no visual-selection API here; this harness tests cursor-based inline completion
- if the server changes undocumented custom methods, this harness may need small updates