copilot-relay 0.3.9 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -243
- package/config.default.yaml +11 -7
- package/dist/main.js +5333 -2490
- package/dist/main.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,271 +1,65 @@
|
|
|
1
1
|
# copilot-relay
|
|
2
2
|
|
|
3
|
+
**Use Claude Code with the models available through your GitHub Copilot subscription.**
|
|
4
|
+
|
|
3
5
|
[](https://github.com/D0n9X1n/copilot-relay/actions/workflows/ci.yml)
|
|
4
6
|
[](https://www.npmjs.com/package/copilot-relay)
|
|
5
|
-
[](https://www.npmjs.com/package/copilot-relay)
|
|
6
|
-
[](https://github.com/D0n9X1n/copilot-relay/pkgs/npm/copilot-relay)
|
|
7
7
|
[](https://nodejs.org/)
|
|
8
|
-
[](https://www.typescriptlang.org/)
|
|
9
|
-
[](https://docs.anthropic.com/en/docs/claude-code/overview)
|
|
10
8
|
[](LICENSE)
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
## Disclaimer
|
|
15
|
-
|
|
16
|
-
This is a research-oriented project and is not affiliated with GitHub, GitHub
|
|
17
|
-
Copilot, Anthropic, or Claude Code. It depends on upstream GitHub Copilot
|
|
18
|
-
services and undocumented compatibility behavior, so Copilot availability, model
|
|
19
|
-
access, API behavior, and runtime stability are not guaranteed.
|
|
20
|
-
|
|
21
|
-
Public API:
|
|
22
|
-
|
|
23
|
-
- `POST /v1/messages`
|
|
24
|
-
- `POST /v1/messages/count_tokens`
|
|
25
|
-
- `GET /v1/models`
|
|
26
|
-
- `GET /healthz`
|
|
27
|
-
- `GET|HEAD /api/hello`
|
|
28
|
-
|
|
29
|
-
`/api/hello` is a static reachability probe Claude Code sends on startup and
|
|
30
|
-
around real traffic. Like `/healthz` it never contacts Copilot, so it proves the
|
|
31
|
-
relay is listening and nothing more.
|
|
32
|
-
|
|
33
|
-
Claude WebSearch is bridge-managed: when the model selects the WebSearch tool,
|
|
34
|
-
the relay executes Copilot `/responses` with `web_search_preview`, then sends the
|
|
35
|
-
retrieved context through a final model pass and returns Claude
|
|
36
|
-
`server_tool_use` / `web_search_tool_result` blocks. The final pass keeps your
|
|
37
|
-
other tools available, so the model can act on what it found in the same turn.
|
|
38
|
-
|
|
39
|
-
Advertising WebSearch no longer costs streaming. The relay reads the model's
|
|
40
|
-
response only as far as it takes to tell whether a search is coming, so a turn
|
|
41
|
-
that never searches streams normally — which is most of them, since Claude Code
|
|
42
|
-
offers the tool on every request.
|
|
43
|
-
|
|
44
|
-
Unknown API routes return `500` and log method, path, selected headers, and
|
|
45
|
-
request payload to help implement compatible endpoints later.
|
|
46
|
-
|
|
47
|
-
Routing:
|
|
48
|
-
|
|
49
|
-
| Requested model | Upstream model |
|
|
50
|
-
| --- | --- |
|
|
51
|
-
| contains `opus` | `claude-opus-5` |
|
|
52
|
-
| `gpt-6-astra[1m]`, plain `gpt-6-astra`, or another non-Opus alias | `gpt-6-astra` |
|
|
53
|
-
|
|
54
|
-
The fresh-install default is `gpt-6-astra`, exposed to Claude Code as
|
|
55
|
-
`gpt-6-astra[1m]`. The selector changes Claude Code's client-side context budgeting
|
|
56
|
-
only; Copilot receives the canonical `gpt-6-astra` ID. It does not enlarge
|
|
57
|
-
upstream capacity. Existing `config.yaml` model choices are never migrated.
|
|
58
|
-
If your account cannot use Astra, startup fails explicitly; choose a model your
|
|
59
|
-
account supports rather than relying on an automatic fallback.
|
|
60
|
-
|
|
61
|
-
Claude Code can still show its built-in Haiku and Sonnet picker entries. The
|
|
62
|
-
managed `model` field sets the startup default but does not restrict
|
|
63
|
-
`availableModels`; selecting any non-Opus alias still follows the GPT route.
|
|
64
|
-
|
|
65
|
-
## Install & run
|
|
66
|
-
|
|
67
|
-
```sh
|
|
68
|
-
npx copilot-relay@latest auth
|
|
69
|
-
npx copilot-relay@latest start
|
|
70
|
-
npx copilot-relay@latest restart
|
|
71
|
-
npx copilot-relay@latest stop
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
With `claudeSetup: true`, `start` manages `ANTHROPIC_BASE_URL`, a dummy
|
|
75
|
-
`ANTHROPIC_AUTH_TOKEN` when auth is absent, and the configured GPT default via
|
|
76
|
-
the top-level `model` field in `~/.claude/settings.json`. Exact
|
|
77
|
-
`gpt-6-astra` and `gpt-5.6-sol` overrides are normalized to Claude-facing
|
|
78
|
-
`[1m]` identities when discovery reports exactly 1M; other reported windows use
|
|
79
|
-
plain GPT IDs with Claude's numeric context setting. Unrelated model choices and
|
|
80
|
-
existing token-budget overrides are preserved.
|
|
81
|
-
|
|
82
|
-
Startup retains Copilot's actual context, prompt, and output limits and exposes
|
|
83
|
-
them on `GET /v1/models`. Managed Claude setup seeds
|
|
84
|
-
`CLAUDE_CODE_MAX_CONTEXT_TOKENS` and `CLAUDE_CODE_MAX_OUTPUT_TOKENS` when absent.
|
|
85
|
-
The default models support 1M total context, with up to 128K output tokens for
|
|
86
|
-
Astra and 64K for Opus. Input text is never shortened; smaller explicit output
|
|
87
|
-
budgets remain respected. See [full-context configuration](wiki/EN-Configuration.md)
|
|
88
|
-
for existing/manual Claude setups and the limits on input plus output.
|
|
89
|
-
|
|
90
|
-
## Config
|
|
91
|
-
|
|
92
|
-
Config lives at `~/.copilot-relay/config.yaml` and is hot-reloaded:
|
|
93
|
-
|
|
94
|
-
```yaml
|
|
95
|
-
host: 127.0.0.1
|
|
96
|
-
port: 4142
|
|
97
|
-
copilotBaseUrl: https://api.githubcopilot.com
|
|
98
|
-
claudeSetup: true
|
|
99
|
-
logLevel: info
|
|
100
|
-
logRetentionDays: 3
|
|
101
|
-
thinkEffort: max
|
|
102
|
-
upstreamTimeoutSeconds: 180
|
|
103
|
-
webSearchBackend:
|
|
104
|
-
gptModel: gpt-6-astra
|
|
105
|
-
opusModel: claude-opus-5
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
copilot-relay writes the resolved config back to this file, so every key is
|
|
109
|
-
present after the first start. Shipped defaults therefore apply to fresh
|
|
110
|
-
installs only — once a value is in your `config.yaml` it is never rewritten by
|
|
111
|
-
an upgrade. To pick up a changed default, edit the key yourself. See
|
|
112
|
-
[Configuration](wiki/EN-Configuration.md) / [配置说明](wiki/ZH-Configuration.md)
|
|
113
|
-
for live model discovery, compatible thinking efforts, and copy-paste updates.
|
|
114
|
-
|
|
115
|
-
`logLevel` controls verbosity:
|
|
116
|
-
|
|
117
|
-
| Level | Logs |
|
|
118
|
-
| --- | --- |
|
|
119
|
-
| `error` | Startup, preflight, and request failures |
|
|
120
|
-
| `info` | Errors plus startup/preflight status, request IDs, model/effort summaries, upstream lifecycle, and local HTTP status codes |
|
|
121
|
-
| `debug` | Info plus detailed Copilot timings and request payloads |
|
|
122
|
-
|
|
123
|
-
Any other `logLevel` value is invalid and stops startup.
|
|
124
|
-
|
|
125
|
-
Valid `thinkEffort` defaults: `low`, `medium`, `high`, `xhigh`, `max`.
|
|
126
|
-
It is a fallback, not a forced override: Claude Code's `output_config.effort`
|
|
127
|
-
wins, followed by the legacy `reasoning_effort` field, then `thinkEffort` when
|
|
128
|
-
neither request field supplies a value. The selected effort is preserved through
|
|
129
|
-
all model and WebSearch passes; existing config values are not rewritten.
|
|
130
|
-
`none` and other invalid explicit defaults fail startup before authentication or
|
|
131
|
-
config write-back, with a clear list of valid choices. They are not silently
|
|
132
|
-
replaced with `max`. Explicit request-level `none` remains model-dependent.
|
|
133
|
-
|
|
134
|
-
`upstreamTimeoutSeconds` controls the maximum time a single Claude request can
|
|
135
|
-
spend waiting on upstream Copilot calls, including chat, Responses, preflight,
|
|
136
|
-
and bridge-managed WebSearch calls. The default is `180`. Set `0` to disable the
|
|
137
|
-
relay deadline for very long requests; client cancellation and provider/transport
|
|
138
|
-
timeouts still apply. Existing saved timeouts are never changed by an upgrade.
|
|
10
|
+
## Features
|
|
139
11
|
|
|
140
|
-
|
|
141
|
-
|
|
12
|
+
- **Claude Code, familiar workflow** — Messages API compatibility, streaming responses, and tool calls.
|
|
13
|
+
- **WebSearch that fits the conversation** — relay-managed search, followed by an answer that can still use your tools.
|
|
14
|
+
- **Your models, your settings** — configurable GPT/Opus routes and reasoning effort; existing selections survive upgrades.
|
|
15
|
+
- **Use the advertised capacity** — discovered context/output limits, without silently shortening your input.
|
|
16
|
+
- **Know what works** — model discovery and opt-in per-model deep checks with clear results.
|
|
17
|
+
- **Choose Claude's upstream protocol** — `claudeUpstreamApi: chat-completions` stays the default; opt into `auto` or `messages` for native Claude transport.
|
|
18
|
+
- **Diagnose offline** — debug mode captures full observed bodies for `copilot-relay replay`; captures contain unredacted prompts and must never be shared wholesale.
|
|
19
|
+
- **Run it your way** — foreground CLI or background service on macOS, Windows, and Linux.
|
|
142
20
|
|
|
143
|
-
|
|
21
|
+
## Quick start
|
|
144
22
|
|
|
145
|
-
|
|
23
|
+
You need **Node.js 22+**, **Claude Code**, and a GitHub account with Copilot access
|
|
24
|
+
to the models you select.
|
|
146
25
|
|
|
147
26
|
```sh
|
|
27
|
+
npm install -g copilot-relay
|
|
148
28
|
copilot-relay auth
|
|
149
29
|
copilot-relay start
|
|
150
|
-
copilot-relay restart
|
|
151
|
-
copilot-relay status
|
|
152
|
-
copilot-relay stop
|
|
153
30
|
```
|
|
154
31
|
|
|
155
|
-
|
|
156
|
-
|
|
32
|
+
Follow the device-login prompt. Keep the relay running in this terminal; by default,
|
|
33
|
+
startup configures Claude Code's connection in `~/.claude/settings.json`.
|
|
34
|
+
Open a **second terminal** and run:
|
|
157
35
|
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
process running (pid 93744, up 1h 16m)
|
|
161
|
-
version 0.2.5
|
|
162
|
-
listening http://127.0.0.1:4142
|
|
163
|
-
health ok (9ms)
|
|
164
|
-
models gpt-6-astra[1m], claude-opus-5
|
|
165
|
-
upstream not checked (use --deep)
|
|
166
|
-
log ~/.copilot-relay/logs/copilot-relay.2026-07-25.log
|
|
167
|
-
config ~/.copilot-relay/config.yaml
|
|
168
|
-
host 127.0.0.1
|
|
169
|
-
port 4142
|
|
170
|
-
copilotBaseUrl https://api.githubcopilot.com
|
|
171
|
-
claudeSetup true
|
|
172
|
-
logLevel info
|
|
173
|
-
logRetentionDays 3
|
|
174
|
-
thinkEffort max
|
|
175
|
-
upstreamTimeoutSeconds 180
|
|
176
|
-
webSearchBackend (unset — uses gptModel)
|
|
177
|
-
gptModel gpt-6-astra
|
|
178
|
-
opusModel claude-opus-5
|
|
179
|
-
host, port and claudeSetup take effect on restart; the rest hot-reload.
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
The `config` block is every key `readAppConfig()` resolved, in
|
|
183
|
-
`config.default.yaml` order. These are the values on disk: eight of them reload
|
|
184
|
-
while the relay runs, while `host`, `port` and `claudeSetup` are read once at
|
|
185
|
-
startup — the block says so rather than leaving you to discover it after an
|
|
186
|
-
edit. `--json` emits the same values under `config`, with `webSearchBackend` as
|
|
187
|
-
`null` when unset so the key set stays the same shape either way.
|
|
188
|
-
|
|
189
|
-
The first line is the CLI you invoked; the `version` row is the build the
|
|
190
|
-
running daemon reports about itself. They differ after an upgrade that has not
|
|
191
|
-
been restarted yet — the new CLI is installed, the old process is still
|
|
192
|
-
serving — and `status` says so rather than letting the header imply the upgrade
|
|
193
|
-
took effect:
|
|
194
|
-
|
|
195
|
-
```text
|
|
196
|
-
version 0.2.6 — MISMATCH, 0.3.0 is installed
|
|
197
|
-
...
|
|
198
|
-
The running relay is 0.2.6; 0.3.0 is installed.
|
|
199
|
-
Restart it to serve the installed version: copilot-relay restart
|
|
36
|
+
```sh
|
|
37
|
+
claude
|
|
200
38
|
```
|
|
201
39
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
`--deep` additionally sends a real request through Copilot. That is the only
|
|
207
|
-
check that proves the relay can actually serve Claude Code — a relay whose
|
|
208
|
-
Copilot token expired an hour ago still answers `/healthz` and `/v1/models`,
|
|
209
|
-
because neither contacts upstream. It is opt-in because it spends a few tokens.
|
|
40
|
+
Configuration lives in `~/.copilot-relay/config.yaml`. Model access depends on your
|
|
41
|
+
account and organization policy; if startup rejects a model, choose an available
|
|
42
|
+
one using the [configuration guide](wiki/EN-Configuration.md).
|
|
210
43
|
|
|
211
|
-
|
|
212
|
-
`1` not running, `2` running but not usable — the health probe failed, or
|
|
213
|
-
`--deep` was requested and failed. `0` requires a live process *and* a passing
|
|
214
|
-
health probe, so a relay that cannot answer `/healthz` never reports success.
|
|
215
|
-
|
|
216
|
-
## Logging
|
|
217
|
-
|
|
218
|
-
At `info`, every model request logs the requested model, upstream model, requested
|
|
219
|
-
think effort, requested thinking, and effective think effort. Missing request
|
|
220
|
-
effort is shown as `unset`, distinct from explicit `none`; full normal request
|
|
221
|
-
payloads remain at `debug`.
|
|
222
|
-
|
|
223
|
-
Upstream failures are logged at `error` with full request and response context in the same log file.
|
|
224
|
-
|
|
225
|
-
Unsupported Claude API requests are logged at `error` with the local method/path
|
|
226
|
-
and detailed request payload.
|
|
227
|
-
|
|
228
|
-
Logs are written to `~/.copilot-relay/logs/copilot-relay.<local-date>.log`. The
|
|
229
|
-
active file rotates at local midnight, and files older than `logRetentionDays`
|
|
230
|
-
local calendar days are deleted. Rotation is what makes retention take effect:
|
|
231
|
-
without it the single log file's mtime was refreshed by every append, so nothing
|
|
232
|
-
ever aged out.
|
|
233
|
-
|
|
234
|
-
Quick inspection:
|
|
44
|
+
Discover models and optionally test one:
|
|
235
45
|
|
|
236
46
|
```sh
|
|
237
|
-
|
|
238
|
-
|
|
47
|
+
copilot-relay models
|
|
48
|
+
copilot-relay models --deep --model claude-opus-5.5
|
|
239
49
|
```
|
|
240
50
|
|
|
241
|
-
|
|
242
|
-
|
|
51
|
+
Deep checks **consume Copilot usage** and test an isolated relay pipeline, not the
|
|
52
|
+
running daemon. Use `copilot-relay status --deep` for daemon health, and
|
|
53
|
+
`copilot-relay stop` when finished.
|
|
243
54
|
|
|
244
|
-
##
|
|
55
|
+
## Go further
|
|
245
56
|
|
|
246
|
-
|
|
247
|
-
setup for macOS, Windows, and Linux, in English and 中文, each covering
|
|
248
|
-
registration, how to verify it is *actually* working rather than merely
|
|
249
|
-
listening, and how to stop it.
|
|
57
|
+
**[Open the Wiki](https://github.com/D0n9X1n/copilot-relay/wiki)** · **[English / 中文](wiki/README.md)**
|
|
250
58
|
|
|
251
|
-
|
|
252
|
-
|
|
59
|
+
- [Configure models and deep checks](wiki/EN-Configuration.md) · [中文](wiki/ZH-Configuration.md)
|
|
60
|
+
- Run at login: [macOS](wiki/EN-macOS-LaunchAgent.md) · [Windows](wiki/EN-Windows-Service.md) · [Linux](wiki/EN-Linux-systemd.md)
|
|
61
|
+
- [Troubleshoot](wiki/EN-Logging-Troubleshooting.md) · [Understand the architecture](wiki/EN-Architecture.md) · [Contribute](wiki/EN-Development.md)
|
|
253
62
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
| Page | Covers |
|
|
259
|
-
| --- | --- |
|
|
260
|
-
| [Architecture](wiki/EN-Architecture.md) ([中文](wiki/ZH-Architecture.md)) | Modules, request and startup flow, public API, runtime files |
|
|
261
|
-
| [Internals](wiki/EN-Internals.md) ([中文](wiki/ZH-Internals.md)) | Translation, streaming, prompt caching, lifecycle, logging invariants |
|
|
262
|
-
| [Development](wiki/EN-Development.md) ([中文](wiki/ZH-Development.md)) | Setup, tests, CI matrix, workflow, releasing |
|
|
263
|
-
| [Configuration](wiki/EN-Configuration.md) ([中文](wiki/ZH-Configuration.md)) | Every config key, hot reload vs restart |
|
|
264
|
-
| [Logs and troubleshooting](wiki/EN-Logging-Troubleshooting.md) ([中文](wiki/ZH-Logging-Troubleshooting.md)) | Log format, grep recipes, failure modes |
|
|
265
|
-
|
|
266
|
-
```sh
|
|
267
|
-
npm install
|
|
268
|
-
npm run typecheck
|
|
269
|
-
npm run build
|
|
270
|
-
npm test
|
|
271
|
-
```
|
|
63
|
+
Unofficial research project; not affiliated with GitHub or Anthropic. Upstream
|
|
64
|
+
services and compatibility can change. Model and tool support are not guaranteed;
|
|
65
|
+
see the Wiki for known limitations. [MIT licensed](LICENSE).
|
package/config.default.yaml
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
#
|
|
3
3
|
# This file is copied to ~/.copilot-relay/config.yaml on first start.
|
|
4
4
|
# Edit the user config file, not this template, for local changes.
|
|
5
|
-
#
|
|
6
|
-
#
|
|
5
|
+
# Valid complete edits hot-reload without rewriting this file.
|
|
6
|
+
# host, port, and claudeSetup require restart.
|
|
7
7
|
#
|
|
8
8
|
# Values here apply to a fresh install only. copilot-relay writes the resolved
|
|
9
9
|
# config back to disk, so once a key exists in your config.yaml it is yours:
|
|
@@ -26,13 +26,12 @@ claudeSetup: true
|
|
|
26
26
|
|
|
27
27
|
# Log verbosity:
|
|
28
28
|
# error - startup/preflight/request failures only
|
|
29
|
-
# info -
|
|
30
|
-
#
|
|
31
|
-
# debug - info logs plus detailed Copilot timings and request payloads
|
|
29
|
+
# info - errors plus status, model/effort and semantic completion summaries
|
|
30
|
+
# debug - info plus full private bodies in ~/.copilot-relay/captures; may contain secrets
|
|
32
31
|
# Any other value is invalid and stops startup.
|
|
33
32
|
logLevel: info
|
|
34
33
|
|
|
35
|
-
# Number of days to keep
|
|
34
|
+
# Number of days to keep relay logs and settled debug captures.
|
|
36
35
|
# Counted in local calendar days: 3 keeps today plus the previous two days.
|
|
37
36
|
# The active log file is copilot-relay.<local-date>.log and rotates at local
|
|
38
37
|
# midnight, which is what makes this setting take effect at all.
|
|
@@ -52,10 +51,15 @@ upstreamTimeoutSeconds: 180
|
|
|
52
51
|
# Leave empty to use gptModel.
|
|
53
52
|
webSearchBackend:
|
|
54
53
|
|
|
54
|
+
# Claude upstream protocol: auto selects advertised native Messages support.
|
|
55
|
+
# Keep the proven chat route until native cache non-regression is measured.
|
|
56
|
+
# Explicit alternatives: auto, messages.
|
|
57
|
+
claudeUpstreamApi: chat-completions
|
|
58
|
+
|
|
55
59
|
# Model routing: requests containing "opus" use opusModel; all others use gptModel.
|
|
56
60
|
#
|
|
57
61
|
# Upstream Copilot model used for non-Opus requests.
|
|
58
62
|
gptModel: gpt-6-astra
|
|
59
63
|
|
|
60
64
|
# Upstream Copilot model used for requests containing "opus".
|
|
61
|
-
opusModel: claude-opus-5
|
|
65
|
+
opusModel: claude-opus-5.5
|