copilot-api-node20 0.19.1 → 0.20.2
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 +125 -126
- package/dist/get-user-BfOVRifT.mjs +1 -0
- package/dist/get-user-DqCcnRgq.mjs +1 -0
- package/dist/main.mjs +2 -0
- package/package.json +7 -7
- package/dist/get-user-BukbT5yw.js +0 -1
- package/dist/get-user-DdXUcoAP.js +0 -1
- package/dist/main.js +0 -24
package/README.md
CHANGED
|
@@ -1,189 +1,190 @@
|
|
|
1
1
|
# copilot-api
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/copilot-api-node20)
|
|
4
|
-
[](https://www.npmjs.com/package/copilot-api-node20)
|
|
4
|
+
[](https://www.npmjs.com/package/copilot-api-node20)
|
|
5
|
+

|
|
6
|
+
[](https://github.com/johnib/copilot-api)
|
|
7
|
+

|
|
8
|
+
[](./LICENSE)
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
One command. No separate API key. Run Claude Code through the Copilot plan you already pay for.
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
npx copilot-api-node20@latest start --claude-code
|
|
13
|
-
```
|
|
10
|
+
A proxy server that turns a GitHub Copilot subscription into fully compatible OpenAI and Anthropic API endpoints. Use Claude Code, Codex CLI, and any tool that speaks the API -- all through the Copilot plan you already pay for, no separate API keys required.
|
|
14
11
|
|
|
15
12
|
---
|
|
16
13
|
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Key Features](#key-features)
|
|
17
|
+
- [Quick Start](#quick-start)
|
|
18
|
+
- [Claude Code](#claude-code)
|
|
19
|
+
- [Codex CLI](#codex-cli)
|
|
20
|
+
- [Web Search](#web-search)
|
|
21
|
+
- [API Endpoints](#api-endpoints)
|
|
22
|
+
- [CLI Reference](#cli-reference)
|
|
23
|
+
- [Commands](#commands)
|
|
24
|
+
- [start Flags](#start-flags)
|
|
25
|
+
- [Telemetry](#telemetry)
|
|
26
|
+
- [Closed Source](#closed-source)
|
|
27
|
+
- [Notices](#notices)
|
|
28
|
+
- [Attribution](#attribution)
|
|
29
|
+
- [License](#license)
|
|
28
30
|
|
|
29
31
|
---
|
|
30
32
|
|
|
31
|
-
##
|
|
33
|
+
## Key Features
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
| Feature | Description |
|
|
36
|
+
|:--|:--|
|
|
37
|
+
| **Full Claude Code support** | All Claude models, streaming, extended thinking, and the complete **1M token context window** |
|
|
38
|
+
| **Full Codex CLI support** | Complete **OpenAI Responses API** implementation purpose-built for Codex CLI |
|
|
39
|
+
| **Web search** | Optional **Tavily-powered web search** available to both Claude Code and Codex sessions |
|
|
40
|
+
| **Dual API compatibility** | OpenAI Chat Completions, Anthropic Messages, and OpenAI Responses APIs side by side |
|
|
41
|
+
| **Zero configuration** | Single command to start -- authenticates via GitHub device-code OAuth |
|
|
35
42
|
|
|
36
|
-
|
|
37
|
-
Payloads forwarded to the Copilot API sometimes contained ANSI escape sequences, invisible Unicode characters, and other malformed content that GitHub's backend rejects. The proxy now sanitizes every JSON payload before forwarding, stripping anything that does not belong.
|
|
38
|
-
|
|
39
|
-
**Token expiry after laptop sleep or network change.**
|
|
40
|
-
The original proxy had no awareness of network state. After a laptop lid close, a VPN reconnect, or a Wi-Fi switch, the next request would fail with a stale Copilot token. A background connectivity monitor now detects network restoration and triggers an immediate token refresh so the very next request succeeds.
|
|
43
|
+
---
|
|
41
44
|
|
|
42
|
-
|
|
43
|
-
GitHub's rate limiter treats different clients differently. Requests that do not look like they come from a real VS Code session get throttled much faster. The proxy now matches VS Code Insiders headers -- machine ID, session ID, editor version, plugin version -- so GitHub treats it as a legitimate client.
|
|
45
|
+
## Quick Start
|
|
44
46
|
|
|
45
|
-
**
|
|
46
|
-
Claude Code injects an `x-anthropic-billing-header` into its requests. When this metadata leaked into the system prompt content forwarded to Copilot, the model would hallucinate on it or the request would be rejected entirely. It is now filtered before forwarding.
|
|
47
|
+
**Prerequisites:** Node.js 20+ (or Bun) and an active GitHub Copilot subscription.
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
GitHub's backend expects specific API version strings and header shapes that change over time. When the proxy's headers drifted out of sync, requests would fail silently. Headers are now kept current with what GitHub's Copilot Chat protocol expects.
|
|
49
|
+
### Claude Code
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
The original OAuth client ID and scopes were insufficient for some operations. Updated to the correct GitHub client ID and broader OAuth scopes.
|
|
51
|
+
Start the proxy with Claude Code mode:
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
```bash
|
|
54
|
+
npx copilot-api-node20@latest start --claude-code
|
|
55
|
+
```
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
On first run, you authenticate via GitHub device-code OAuth. Once authenticated, the proxy starts on `http://localhost:4141` and prints a ready-to-paste command. In another terminal:
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
```bash
|
|
60
|
+
ANTHROPIC_BASE_URL=http://localhost:4141 claude
|
|
61
|
+
```
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
To skip the interactive model picker, specify models upfront:
|
|
62
64
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
```bash
|
|
66
|
+
npx copilot-api-node20@latest start \
|
|
67
|
+
--claude-code \
|
|
68
|
+
--model claude-opus-4.6-1m \
|
|
69
|
+
--small-model claude-haiku-4.5
|
|
70
|
+
```
|
|
65
71
|
|
|
66
|
-
|
|
67
|
-
Latest model mappings are included, covering `claude-opus-4.6`, `claude-sonnet-4.6`, `claude-sonnet-4.5`, `claude-sonnet-4`, `claude-haiku-4.5`, and their `-1m` / `-fast` suffix variants.
|
|
72
|
+
### Codex CLI
|
|
68
73
|
|
|
69
|
-
|
|
70
|
-
Invalid model names are rejected early with a clear error message. No more forwarding garbage to GitHub and getting a cryptic 400 back.
|
|
74
|
+
Start the proxy with Codex mode:
|
|
71
75
|
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
```bash
|
|
77
|
+
npx copilot-api-node20@latest start --codex --model gpt-5.3-codex
|
|
78
|
+
```
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
Available models and their context windows are printed on boot so you can verify what your Copilot plan provides before sending a single request.
|
|
80
|
+
Configure `~/.codex/config.toml`:
|
|
77
81
|
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
```toml
|
|
83
|
+
model = "gpt-5.3-codex"
|
|
84
|
+
model_provider = "local"
|
|
80
85
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
86
|
+
[model_providers.local]
|
|
87
|
+
name = "Local Server"
|
|
88
|
+
base_url = "http://localhost:4141/v1"
|
|
89
|
+
env_key = "OPENAI_API_KEY"
|
|
90
|
+
```
|
|
84
91
|
|
|
85
|
-
|
|
92
|
+
Then run:
|
|
86
93
|
|
|
87
94
|
```bash
|
|
88
|
-
|
|
95
|
+
OPENAI_API_KEY=dummy codex
|
|
89
96
|
```
|
|
90
97
|
|
|
91
|
-
|
|
98
|
+
### Web Search
|
|
92
99
|
|
|
93
|
-
|
|
100
|
+
Provide a [Tavily](https://tavily.com) API key to enable web search tool calls in both Claude Code and Codex sessions:
|
|
94
101
|
|
|
95
102
|
```bash
|
|
96
|
-
npx copilot-api-node20@latest start
|
|
97
|
-
--claude-code \
|
|
98
|
-
--model claude-sonnet-4 \
|
|
99
|
-
--small-model claude-haiku-4.5
|
|
103
|
+
npx copilot-api-node20@latest start --claude-code --tavily-api-key <key>
|
|
100
104
|
```
|
|
101
105
|
|
|
106
|
+
Alternatively, set `TAVILY_API_KEY` as an environment variable. The proxy operates normally when no key is provided -- web search is simply unavailable.
|
|
107
|
+
|
|
102
108
|
---
|
|
103
109
|
|
|
104
|
-
## API
|
|
110
|
+
## API Endpoints
|
|
105
111
|
|
|
106
|
-
|
|
107
|
-
|---|---|---|
|
|
108
|
-
| `POST` | `/v1/chat/completions` | OpenAI (streaming + non-streaming) |
|
|
109
|
-
| `POST` | `/v1/messages` | Anthropic (streaming + non-streaming) |
|
|
110
|
-
| `GET` | `/v1/models` | OpenAI |
|
|
111
|
-
| `POST` | `/v1/embeddings` | OpenAI |
|
|
112
|
-
| `POST` | `/v1/messages/count_tokens` | Anthropic (stub) |
|
|
113
|
-
| `GET` | `/usage` | Web dashboard |
|
|
112
|
+
All endpoints are served at `http://localhost:4141` by default.
|
|
114
113
|
|
|
115
|
-
|
|
114
|
+
| Method | Path | Compatibility |
|
|
115
|
+
|:--|:--|:--|
|
|
116
|
+
| `POST` | `/v1/chat/completions` | OpenAI Chat Completions |
|
|
117
|
+
| `POST` | `/v1/responses` | OpenAI Responses API |
|
|
118
|
+
| `POST` | `/v1/messages` | Anthropic Messages |
|
|
119
|
+
| `POST` | `/v1/messages/count_tokens` | Anthropic Token Counting |
|
|
120
|
+
| `POST` | `/v1/embeddings` | OpenAI Embeddings |
|
|
121
|
+
| `GET` | `/v1/models` | OpenAI Models |
|
|
122
|
+
All OpenAI-compatible routes are also available without the `/v1/` prefix.
|
|
116
123
|
|
|
117
124
|
---
|
|
118
125
|
|
|
119
|
-
##
|
|
126
|
+
## CLI Reference
|
|
120
127
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
copilot-api
|
|
126
|
-
|
|
128
|
+
### Commands
|
|
129
|
+
|
|
130
|
+
| Command | Description |
|
|
131
|
+
|:--|:--|
|
|
132
|
+
| `copilot-api start` | Start the proxy server |
|
|
133
|
+
| `copilot-api auth` | Authenticate with GitHub |
|
|
134
|
+
| `copilot-api check-usage` | Display Copilot usage quota |
|
|
135
|
+
| `copilot-api debug` | Print diagnostic information |
|
|
136
|
+
|
|
137
|
+
### `start` Flags
|
|
127
138
|
|
|
128
|
-
|
|
139
|
+
> `--claude-code` and `--codex` are mutually exclusive.
|
|
140
|
+
|
|
141
|
+
<details>
|
|
142
|
+
<summary>Full flag reference</summary>
|
|
143
|
+
|
|
144
|
+
<br>
|
|
129
145
|
|
|
130
146
|
| Flag | Alias | Default | Description |
|
|
131
|
-
|
|
147
|
+
|:--|:--|:--|:--|
|
|
132
148
|
| `--port` | `-p` | `4141` | Port to listen on |
|
|
133
|
-
| `--claude-code` | `-c` |
|
|
134
|
-
| `--
|
|
135
|
-
| `--
|
|
136
|
-
| `--
|
|
137
|
-
| `--
|
|
138
|
-
| `--
|
|
139
|
-
| `--timeout` | `-t` | `600000` | API timeout in milliseconds (default: 10 minutes) |
|
|
149
|
+
| `--claude-code` | `-c` | | Enable Claude Code compatibility mode |
|
|
150
|
+
| `--codex` | | | Enable Codex CLI compatibility mode |
|
|
151
|
+
| `--model` | `-m` | | Primary model to use |
|
|
152
|
+
| `--small-model` | `-s` | | Lightweight model for fast tasks (Claude Code) |
|
|
153
|
+
| `--rate-limit` | `-r` | | Minimum seconds between requests |
|
|
154
|
+
| `--timeout` | `-t` | `600000` | Request timeout in ms (default 10 min) |
|
|
140
155
|
| `--account-type` | `-a` | `individual` | `individual`, `business`, or `enterprise` |
|
|
141
|
-
| `--github-token` | `-g` |
|
|
142
|
-
| `--
|
|
156
|
+
| `--github-token` | `-g` | | Provide a GitHub token directly (skips OAuth) |
|
|
157
|
+
| `--show-token` | | | Display tokens on fetch and refresh |
|
|
158
|
+
| `--tavily-api-key` | | | Tavily API key for web search |
|
|
159
|
+
| `--verbose` | `-v` | | Enable debug-level logging |
|
|
143
160
|
|
|
144
|
-
|
|
161
|
+
</details>
|
|
145
162
|
|
|
146
163
|
---
|
|
147
164
|
|
|
148
|
-
##
|
|
149
|
-
|
|
150
|
-
```bash
|
|
151
|
-
docker build -t copilot-api .
|
|
152
|
-
|
|
153
|
-
docker run -p 4141:4141 \
|
|
154
|
-
-v $(pwd)/copilot-data:/root/.local/share/copilot-api \
|
|
155
|
-
copilot-api
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
To inject a pre-authenticated token at build time:
|
|
165
|
+
## Telemetry
|
|
159
166
|
|
|
160
|
-
|
|
161
|
-
docker build --build-arg GH_TOKEN=your_token -t copilot-api .
|
|
162
|
-
docker run -p 4141:4141 copilot-api
|
|
163
|
-
```
|
|
167
|
+
This tool collects anonymous usage telemetry via [OpenTelemetry](https://opentelemetry.io/). Only operational metrics are collected -- request counts, latency, model usage, and error rates. No prompts, completions, or personal information is ever collected.
|
|
164
168
|
|
|
165
|
-
|
|
169
|
+
**By using copilot-api, you agree to this telemetry data collection.**
|
|
166
170
|
|
|
167
171
|
---
|
|
168
172
|
|
|
169
|
-
##
|
|
173
|
+
## Closed Source
|
|
170
174
|
|
|
171
|
-
|
|
172
|
-
2. The proxy displays a device code and opens GitHub in your browser.
|
|
173
|
-
3. Enter the code on GitHub to authorize.
|
|
174
|
-
4. The proxy exchanges the device code for an access token.
|
|
175
|
-
5. The access token is used to obtain a Copilot session token.
|
|
176
|
-
6. Tokens are persisted to disk and refreshed automatically.
|
|
175
|
+
The source code is not publicly available.
|
|
177
176
|
|
|
178
|
-
|
|
177
|
+
This fork represents ~9 months of sustained engineering work -- bug fixes, new features, and hardening that go well beyond the original project. Keeping it closed-source protects that investment and ensures a single, well-maintained distribution.
|
|
178
|
+
|
|
179
|
+
The original open-source project is available at [ericc-ch/copilot-api](https://github.com/ericc-ch/copilot-api).
|
|
179
180
|
|
|
180
181
|
---
|
|
181
182
|
|
|
182
183
|
## Notices
|
|
183
184
|
|
|
184
|
-
This project relies on reverse-engineered, undocumented GitHub APIs. It is **not
|
|
185
|
+
This project relies on reverse-engineered, undocumented GitHub APIs. It is **not affiliated with or endorsed by GitHub, Microsoft, Anthropic, or OpenAI** and may break without notice.
|
|
185
186
|
|
|
186
|
-
- Use
|
|
187
|
+
- Use `--rate-limit` to throttle requests and reduce abuse-detection risk.
|
|
187
188
|
- Review the [GitHub Acceptable Use Policies](https://docs.github.com/en/site-policy/acceptable-use-policies/github-acceptable-use-policies) and [GitHub Copilot Terms](https://docs.github.com/en/site-policy/github-terms/github-terms-for-additional-products-and-features#github-copilot) before use.
|
|
188
189
|
- This software is provided as-is with no warranty.
|
|
189
190
|
|
|
@@ -191,14 +192,12 @@ This project relies on reverse-engineered, undocumented GitHub APIs. It is **not
|
|
|
191
192
|
|
|
192
193
|
## Attribution
|
|
193
194
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
Erick built the foundation that makes all of this possible: the authentication flow, the API translation layer, the streaming implementation. This fork exists because his work was good enough to use in production -- and production is where the edge cases live.
|
|
195
|
+
Originally created by **Erick Christian** -- [ericc-ch/copilot-api](https://github.com/ericc-ch/copilot-api). His work built the foundation: authentication flow, API translation layer, and streaming implementation.
|
|
197
196
|
|
|
198
|
-
|
|
197
|
+
This fork has diverged significantly over ~9 months with extensive bug fixes and major new features -- Anthropic Messages API, OpenAI Responses API, Claude Code mode, Codex CLI support, web search integration, usage telemetry, and more. It is maintained as a separate project by [johnib](https://github.com/johnib).
|
|
199
198
|
|
|
200
|
-
|
|
199
|
+
---
|
|
201
200
|
|
|
202
201
|
## License
|
|
203
202
|
|
|
204
|
-
[MIT](LICENSE)
|
|
203
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import t from"consola";import e from"node:fs/promises";import o from"node:os";import i from"node:path";import{SpanKind as r,SpanStatusCode as a,metrics as s,trace as n}from"@opentelemetry/api";import{SeverityNumber as c,logs as l}from"@opentelemetry/api-logs";import{OTLPLogExporter as p}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPMetricExporter as u}from"@opentelemetry/exporter-metrics-otlp-http";import{OTLPTraceExporter as d}from"@opentelemetry/exporter-trace-otlp-http";import{resourceFromAttributes as m}from"@opentelemetry/resources";import{BatchLogRecordProcessor as h}from"@opentelemetry/sdk-logs";import{PeriodicExportingMetricReader as g}from"@opentelemetry/sdk-metrics";import{NodeSDK as f}from"@opentelemetry/sdk-node";import{ATTR_SERVICE_INSTANCE_ID as y,ATTR_SERVICE_NAME as v,ATTR_SERVICE_VERSION as _}from"@opentelemetry/semantic-conventions";import{request as b}from"undici";import{createHash as k,randomBytes as C,randomUUID as T}from"node:crypto";const E=i.join(o.homedir(),".local","share","copilot-api"),S={APP_DIR:E,GITHUB_TOKEN_PATH:i.join(E,"github_token"),MACHINE_ID_PATH:i.join(E,"machine_id"),SESSION_ID_PATH:i.join(E,"session_id")};async function I(){await e.mkdir(S.APP_DIR,{recursive:!0}),await w(S.GITHUB_TOKEN_PATH),await w(S.SESSION_ID_PATH)}async function w(t){try{await e.access(t,e.constants.W_OK)}catch{await e.writeFile(t,""),await e.chmod(t,384)}}const A=6e5,R={accountType:"individual",manualApprove:!1,rateLimitWait:!1,showToken:!1,timeoutMs:A,connectivity:{probeEndpoints:["https://api.github.com","https://www.google.com","https://1.1.1.1"],fastProbeInterval:5e3,slowProbeInterval:1e4,timeoutMs:5e3,jitterMaxMs:1e3,connectionPooling:!0,dnsCache:!0,h2:!1,h2Keepalive:!1}},x=t=>t>=1e5||t>=1e4?`${Math.round(t/1e3)}K`:t>=1e3?`${(t/1e3).toFixed(1)}K`:t.toString(),O=(t,e)=>t.padEnd(e),$=t=>{let e=[];if(t.model){let o=O(t.model,18);e.push(o)}if(t.tokenUsage){let o=t.tokenUsage,i=(o.inputTokens||0)+(o.outputTokens||0),r=t.model?((t,e)=>{if(!R.models)return"";let o=R.models.data.find(t=>t.id===e);if(!o)return"";let i=o.capabilities.limits?.max_context_window_tokens;return i?` (${(t/i*100).toFixed(1)}%)`:""})(i,t.model):"",a=O(`↑${x(o.inputTokens||0).padStart(5)} │ ↓${x(o.outputTokens||0).padStart(5)}`,18),s=x(i),n=r?`${s}${r.padStart(15-s.length)}`:s.padEnd(15);e.push(`Tokens: ${a} | Context: ${n}`)}else if(t.model){let t=O("N/A",18),o="N/A".padEnd(15);e.push(`Tokens: ${t} | Context: ${o}`)}if(t._d1){let o=O(`${Math.round(t._d1)}ms`,8);e.push(`API: ${o}`)}return e.length>0?` | ${e.join(" | ")}`:""},P={completionCallbacks:new Map,registerCompletion(t,e,o){this.completionCallbacks.set(t,{context:e,startTime:o,requestId:t})},executeCompletion(t){let e=this.completionCallbacks.get(t);e&&(this.logCompletion(e),this.completionCallbacks.delete(t))},logCompletion(e){let{context:o,startTime:i}=e,r=Date.now()-i,a=o.get("requestData"),s=` --\x3e ${O(o.req.method,4)}${O(o.req.path,21)}${O(o.res.status.toString(),3)} ${O(`${r}ms`,8)}`;a&&(s+=$(a)),t.info(s),vt(c.INFO,"INFO","Request completed",{"http.method":o.req.method,"http.path":o.req.path,"http.status_code":o.res.status,"copilot_api.duration_ms":r,...a?.model&&{"copilot_api.model":a.model},...a?._d1&&{"copilot_api.copilot_duration_ms":Math.round(a._d1)},...a?.tokenUsage?.inputTokens&&{"copilot_api.input_tokens":a.tokenUsage.inputTokens},...a?.tokenUsage?.outputTokens&&{"copilot_api.output_tokens":a.tokenUsage.outputTokens}})},logRateLimit(e,o){let{context:i,startTime:r}=e,a=Date.now()-r,s=(o.headers.get("x-ratelimit-exceeded")||"").split(":")[1]||"unknown",n=o.headers.get("retry-after")||o.headers.get("x-ratelimit-user-retry-after")||"?",c=`⚠ --\x3e ${O(i.req.method,4)}${O(i.req.path,21)}${O("429",3)} ${O(`${a}ms`,8)}`;c+=` | Rate limited (${n}s retry) | ${s}`;let l=i.get("requestData");if(l?._d1){c+=` | API: ${O(`${Math.round(l._d1)}ms`,8)}`}t.info(c)},cleanup(){let t=Date.now()-3e5;for(let[e,o]of this.completionCallbacks)o.startTime<t&&this.completionCallbacks.delete(e);if(this.completionCallbacks.size>1e3){let t=Array.from(this.completionCallbacks.entries()).sort(([,t],[,e])=>t.startTime-e.startTime),e=t.slice(0,t.length-1e3);for(let[t]of e)this.completionCallbacks.delete(t)}}};setInterval(()=>P.cleanup(),6e4);let N,H,M=Date.now();const q="https://api.honeycomb.io",j={"x-honeycomb-team":"hcaik_01km2y7yf1rrn70xvxce5kx9dyz936dwm21b9bgvnwf3pxq0cmqkcwha8n"};function F(t,e){e&&(M=e),H=crypto.randomUUID(),N=new f({resource:m({[v]:"copilot-api",[_]:t,[y]:H}),traceExporter:new d({url:`${q}/v1/traces`,headers:j}),metricReader:new g({exporter:new u({url:`${q}/v1/metrics`,headers:j}),exportIntervalMillis:15e3}),logRecordProcessors:[new h(new p({url:`${q}/v1/logs`,headers:j}))],instrumentations:[]}),N.start()}async function D(){N&&await N.shutdown()}const U=n.getTracer("copilot-api"),L=s.getMeter("copilot-api"),z=l.getLogger("copilot-api"),G=L.createCounter("copilot_api.requests.total",{unit:"{request}",description:"Total requests received"}),V=L.createCounter("copilot_api.requests.errors",{unit:"{error}",description:"Total error responses"}),K=L.createCounter("copilot_api.tokens.input",{unit:"{token}",description:"Total input tokens consumed"}),W=L.createCounter("copilot_api.tokens.output",{unit:"{token}",description:"Total output tokens generated"}),X=L.createCounter("copilot_api.tokens.cached",{unit:"{token}",description:"Total cached prompt tokens"}),B=L.createCounter("copilot_api.rate_limit.triggers",{unit:"{trigger}",description:"Rate limit trigger count"}),J=L.createCounter("copilot_api.model_validation.errors",{unit:"{error}",description:"Model validation failures"}),Y=L.createCounter("copilot_api.model_mapping.mappings",{unit:"{mapping}",description:"Model name normalizations"}),Z=L.createCounter("copilot_api.token_refresh.attempts",{unit:"{attempt}",description:"Token refresh attempts"}),Q=L.createCounter("copilot_api.token_refresh.failures",{unit:"{failure}",description:"Token refresh final failures"}),tt=L.createCounter("copilot_api.connectivity.checks",{unit:"{check}",description:"Connectivity probe results"}),et=L.createCounter("copilot_api.connectivity.transitions",{unit:"{transition}",description:"Connectivity state transitions"}),ot=L.createCounter("copilot_api.upstream.requests",{unit:"{request}",description:"Upstream API calls"}),it=L.createCounter("copilot_api.stream.chunks",{unit:"{chunk}",description:"Total SSE chunks sent"}),rt=L.createCounter("copilot_api.approval.decisions",{unit:"{decision}",description:"Manual approval decisions"}),at=L.createCounter("copilot_api.h2_keepalive.pings",{unit:"{ping}",description:"HTTP/2 keepalive pings sent"}),st=L.createCounter("copilot_api.h2.connections",{unit:"{connection}",description:"HTTP/2 connection lifecycle events"}),nt=L.createHistogram("copilot_api.request.duration",{unit:"ms",description:"Total request duration"}),ct=L.createHistogram("copilot_api.copilot.duration",{unit:"ms",description:"Upstream Copilot API call duration"}),lt=L.createHistogram("copilot_api.stream.duration",{unit:"ms",description:"Duration of SSE streaming phase"}),pt=L.createHistogram("copilot_api.rate_limit.wait_duration",{unit:"ms",description:"Duration of rate limit waits"}),ut=L.createHistogram("copilot_api.translation.duration",{unit:"ms",description:"Translation layer processing time"}),dt=L.createHistogram("copilot_api.token_refresh.duration",{unit:"ms",description:"Token refresh duration"}),mt=L.createHistogram("copilot_api.connectivity.probe_duration",{unit:"ms",description:"Individual connectivity probe duration"}),ht=L.createHistogram("copilot_api.tokens.per_request.input",{unit:"{token}",description:"Input tokens per request distribution"}),gt=L.createHistogram("copilot_api.tokens.per_request.output",{unit:"{token}",description:"Output tokens per request distribution"}),ft=L.createHistogram("copilot_api.stream.chunks_per_request",{unit:"{chunk}",description:"Chunks per streaming request"}),yt=L.createHistogram("copilot_api.approval.wait_duration",{unit:"ms",description:"Time waiting for manual approval"});function vt(t,e,o,i){let r=n.getActiveSpan()?.spanContext();z.emit({severityNumber:t,severityText:e,body:o,attributes:{...i,...r&&{"trace.id":r.traceId,"span.id":r.spanId}}})}function _t(t,e=""){let o={};if(null==t)return o;if("object"!=typeof t)return("string"==typeof t||"number"==typeof t||"boolean"==typeof t)&&e&&(o[e]=t),o;if(Array.isArray(t))return e&&(o[e]=JSON.stringify(t)),o;for(let[i,r]of Object.entries(t)){let t=e?`${e}.${i}`:i;void 0===r||"function"==typeof r||(null===r?o[t]="null":"object"!=typeof r||Array.isArray(r)?Array.isArray(r)?o[t]=JSON.stringify(r):("string"==typeof r||"number"==typeof r||"boolean"==typeof r)&&(o[t]=r):Object.assign(o,_t(r,t)))}return o}L.createObservableGauge("copilot_api.connectivity.status",{unit:"{status}",description:"1 = online, 0 = offline"}).addCallback(t=>{t.observe(Et.getConnectivityStats().isOnline?1:0)}),L.createObservableGauge("copilot_api.connectivity.consecutive_failures",{unit:"{failure}",description:"Current consecutive connectivity failure count"}).addCallback(t=>{t.observe(Et.getConnectivityStats().consecutiveFailures)}),L.createObservableGauge("copilot_api.models.available",{unit:"{model}",description:"Number of available models"}).addCallback(t=>{t.observe(R.models?.data.length??0)}),L.createObservableGauge("copilot_api.completion_logger.pending",{unit:"{callback}",description:"Number of pending completion callbacks"}).addCallback(t=>{t.observe(P.completionCallbacks.size)}),L.createObservableGauge("copilot_api.uptime",{unit:"s",description:"Server uptime in seconds"}).addCallback(t=>{t.observe((Date.now()-M)/1e3)});const bt=new Set(["authorization","cookie","set-cookie","x-honeycomb-team","x-api-key","proxy-authorization"]);function kt(t,e,o){for(let[i,r]of Object.entries(o)){let o=i.toLowerCase();bt.has(o)||t.setAttribute(`http.${e}.header.${o}`,r)}}async function Ct(t){let{spanName:e,url:o,target:i,method:s="GET",headers:n,body:c,signal:l,extraAttributes:p}=t,u=U.startSpan(e,{kind:r.CLIENT,attributes:{"http.method":s,"url.full":o,"copilot_api.target":i,...p}});n&&kt(u,"request",n);try{let t=await fetch(o,{method:s,headers:n,body:c,signal:l});return u.setAttribute("http.response.status_code",t.status),function(t,e){e.headers.forEach((e,o)=>{let i=o.toLowerCase();bt.has(i)||t.setAttribute(`http.response.header.${i}`,e)})}(u,t),ot.add(1,{target:i,status_code:String(t.status)}),t.ok||u.setStatus({code:a.ERROR,message:`HTTP ${t.status}`}),{response:t,span:u}}catch(t){let e=t instanceof Error?t:Error(String(t));throw u.setStatus({code:a.ERROR,message:e.message}),u.recordException(e),u.end(),t}}async function Tt(t){let{spanName:e,url:o,target:i,method:s="POST",headers:n,body:c,signal:l,headersTimeout:p,bodyTimeout:u,extraAttributes:d,dispatcher:m}=t,h=U.startSpan(e,{kind:r.CLIENT,attributes:{"http.method":s,"url.full":o,"copilot_api.target":i,"copilot_api.h2.enabled":void 0!==m,...d}});kt(h,"request",n);try{let{statusCode:t,headers:e,body:r}=await b(o,{method:s,headers:n,body:c,signal:l,headersTimeout:p,bodyTimeout:u,dispatcher:m});h.setAttribute("http.response.status_code",t);for(let[t,o]of Object.entries(e)){let e=t.toLowerCase();void 0!==o&&!bt.has(e)&&h.setAttribute(`http.response.header.${e}`,Array.isArray(o)?o.join(", "):o)}return ot.add(1,{target:i,status_code:String(t)}),t>=400&&h.setStatus({code:a.ERROR,message:`HTTP ${t}`}),{statusCode:t,headers:e,body:r,span:h}}catch(t){let e=t instanceof Error?t:Error(String(t));throw h.setStatus({code:a.ERROR,message:e.message}),h.recordException(e),h.end(),t}}const Et=new class extends EventTarget{isOnline=!0;lastChecked=(new Date).toISOString();consecutiveFailures=0;lastErrorType;lastErrorMessage;lastSuccessfulEndpoint;endpointFailureStats={};checkInterval;abortController;on(t,e){return this.addEventListener(t,e),this}off(t,e){return this.removeEventListener(t,e),this}start(){t.debug("Starting connectivity monitor",{probeEndpoints:R.connectivity.probeEndpoints,fastInterval:R.connectivity.fastProbeInterval}),this.scheduleNextCheck()}stop(){t.debug("Stopping connectivity monitor"),this.checkInterval&&=void clearTimeout(this.checkInterval),this.abortController&&=void this.abortController.abort()}scheduleNextCheck(){this.checkInterval&&clearTimeout(this.checkInterval);let e=(this.isOnline?R.connectivity.slowProbeInterval:R.connectivity.fastProbeInterval)+Math.random()*R.connectivity.jitterMaxMs;this.checkInterval=setTimeout(()=>{this.performConnectivityCheck().catch(e=>{t.error("Connectivity check failed:",e)})},e)}async performConnectivityCheck(){let e=U.startSpan("copilot_api.connectivity.probe");this.abortController=new AbortController;let o=setTimeout(()=>this.abortController?.abort(),R.connectivity.timeoutMs);try{let i=!1;for(let e of R.connectivity.probeEndpoints)try{let t=performance.now(),o=await fetch(e,{method:"HEAD",signal:this.abortController.signal,headers:{"User-Agent":"copilot-api-connectivity-monitor/1.0",...R.connectivity.dnsCache&&{"Cache-Control":"max-age=300"}}}),r=performance.now()-t;if(o.ok){i=!0,this.lastSuccessfulEndpoint=e,mt.record(r,{endpoint:e,result:"success"});break}mt.record(r,{endpoint:e,result:"failed"})}catch(o){this.endpointFailureStats[e]=(this.endpointFailureStats[e]||0)+1,t.debug(`Probe failed for ${e}:`,o)}this.updateConnectivityState(i);let r=i?"online":"offline";e.setAttribute("copilot_api.connectivity.result",r),e.setAttribute("copilot_api.connectivity.consecutive_failures",this.consecutiveFailures),this.lastSuccessfulEndpoint&&e.setAttribute("copilot_api.connectivity.successful_endpoint",this.lastSuccessfulEndpoint),tt.add(1,{result:i?"online":"offline"})}catch(t){this.handleConnectivityError(t)}finally{clearTimeout(o),e.end(),this.scheduleNextCheck()}}updateConnectivityState(e){let o=this.isOnline;if(this.isOnline=e,this.lastChecked=(new Date).toISOString(),e){let e=this.consecutiveFailures;this.consecutiveFailures>0&&t.info(`Connectivity restored after ${this.consecutiveFailures} failures`),this.consecutiveFailures=0,this.lastErrorType=void 0,this.lastErrorMessage=void 0,o||(this.dispatchEvent(new CustomEvent("online")),et.add(1,{from:"offline",to:"online"}),vt(c.INFO,"INFO","Connectivity restored",{"copilot_api.connectivity.consecutive_failures_before_recovery":e}))}else this.consecutiveFailures++,o&&(t.warn("Connectivity lost"),this.dispatchEvent(new CustomEvent("offline")),et.add(1,{from:"online",to:"offline"}),vt(c.WARN,"WARN","Connectivity lost",{"copilot_api.connectivity.consecutive_failures":this.consecutiveFailures}))}handleConnectivityError(e){this.lastErrorType=e.name,this.lastErrorMessage=e.message,t.error("Connectivity check failed:",e),this.updateConnectivityState(!1)}getConnectivityStats(){return{isOnline:this.isOnline,lastChecked:this.lastChecked,consecutiveFailures:this.consecutiveFailures,lastErrorType:this.lastErrorType,lastErrorMessage:this.lastErrorMessage}}getPerformanceStats(){let t=this.isOnline?R.connectivity.slowProbeInterval:R.connectivity.fastProbeInterval;return{currentInterval:t,nextCheckEstimate:new Date(Date.now()+t+Math.random()*R.connectivity.jitterMaxMs).toISOString(),lastSuccessfulEndpoint:this.lastSuccessfulEndpoint,endpointFailureStats:{...this.endpointFailureStats},jitterEnabled:R.connectivity.jitterMaxMs>0,connectionPooling:R.connectivity.connectionPooling,dnsCache:R.connectivity.dnsCache}}},St=()=>({"content-type":"application/json",accept:"application/json"}),It="0.43.2026033104",wt=`copilot-chat/${It}`,At=`GitHubCopilotChat/${It}`,Rt=t=>{let e=k("sha256");return e.update(process.platform),e.update(process.arch),e.update(process.env.USER||process.env.USERNAME||"anonymous"),e.update(o.hostname()),e.update(t),e.update(Date.now().toString()),e.update(C(16)),e.digest("hex")},xt=async t=>{let o=(t=>{let e=t.replaceAll(/[^\w.-]/g,"_").trim();if(0===e.length||"."===e||".."===e||/^[_.]+$/.test(e))throw Error("Invalid GitHub username: cannot be empty or consist only of special characters after sanitization");return`${S.MACHINE_ID_PATH}_${e}`})(t);try{let t=await e.readFile(o,"utf8");if(t.trim())return t.trim()}catch{}let i=Rt(t);return await e.writeFile(o,i),await e.chmod(o,384),i},Ot=async()=>{try{let t=await e.readFile(S.SESSION_ID_PATH,"utf8");if(t.trim())return t.trim()}catch{}let t=T();return await e.writeFile(S.SESSION_ID_PATH,t),await e.chmod(S.SESSION_ID_PATH,384),t},$t=async(t,e)=>{t.machineId||=await xt(e),t.sessionId||=await Ot()},Pt=t=>"individual"===t.accountType?"https://api.githubcopilot.com":`https://api.${t.accountType}.githubcopilot.com`,Nt=(t,e=!1)=>{if(!t.machineId||!t.sessionId)throw Error("VSCode identifiers not initialized. Call initializeVSCodeIdentifiers() during startup.");let o=T(),i={Authorization:`Bearer ${t._t1}`,"Content-Type":"application/json",accept:"*/*","accept-encoding":"br, gzip, deflate","accept-language":"*","sec-fetch-mode":"cors","Copilot-Integration-Id":"vscode-chat","Editor-Version":`vscode/${t._v1}`,"Editor-Plugin-Version":wt,"User-Agent":At,"VScode-MachineId":t.machineId,"VScode-SessionId":t.sessionId,"OpenAI-Intent":"conversation-agent","X-Interaction-Type":"conversation-agent","X-Agent-Task-Id":o,"X-VSCode-User-Agent-Library-Version":"node-fetch","X-GitHub-Api-Version":"2025-05-01","X-Interaction-Id":T(),"X-Request-Id":o};return e&&(i["copilot-vision-request"]="true"),i},Ht="https://api.github.com",Mt=t=>({"content-type":"application/json",accept:"application/json",authorization:`token ${t._t2}`,"editor-version":`vscode/${t._v1}`,"editor-plugin-version":wt,"user-agent":At,"x-github-api-version":"2025-04-01","x-vscode-user-agent-library-version":"node-fetch"}),qt="https://github.com",jt="01ab8ac9400c4e429b23",Ft=["user:email"].join(" ");var Dt=class extends Error{response;constructor(t,e){super(t),this.response=e}};async function Ut(e,o){let i=n.getActiveSpan();if(o instanceof Dt&&429===o.response.status){let t=e.get("requestId"),r=P.completionCallbacks.get(t);r&&(P.logRateLimit(r,o.response),P.completionCallbacks.delete(t)),B.add(1,{action:"rejected",source:"upstream"});let s,n=await o.response.text();try{s=JSON.parse(n)}catch{s={error:{message:n,type:"error"}}}return i?.setStatus({code:a.ERROR,message:"Rate limited by upstream"}),i?.setAttribute("copilot_api.error_type","rate_limit_upstream"),vt(c.WARN,"WARN","Upstream rate limit hit",{"copilot_api.status_code":429,"http.path":e.req.path,"copilot_api.error_type":"rate_limit_upstream"}),e.json(s,429)}if(t.error("Error occurred:",o),o instanceof Dt){let r,s=await o.response.text();try{r=JSON.parse(s)}catch{r=s}return t.error("HTTP error:",r),i?.setStatus({code:a.ERROR,message:o.message}),i?.recordException(o),i?.setAttribute("copilot_api.error_type","HTTPError"),vt(c.ERROR,"ERROR",`HTTP error: ${o.message}`,{"copilot_api.status_code":o.response.status,"http.path":e.req.path,"copilot_api.error_type":"HTTPError"}),e.json({error:{message:s,type:"error"}},o.response.status)}let r=o instanceof Error?o:Error(String(o));return i?.setStatus({code:a.ERROR,message:r.message}),i?.recordException(r),i?.setAttribute("copilot_api.error_type",r.name),vt(c.ERROR,"ERROR",`Unhandled error: ${r.message}`,{"copilot_api.status_code":500,"http.path":e.req.path,"copilot_api.error_type":r.name}),e.json({error:{message:r.message,type:"error"}},500)}async function Lt(){let t=`${Ht}/user`,e=R.timeoutMs,o=new AbortController,i=setTimeout(()=>o.abort(),e);try{let{response:e,span:i}=await Ct({spanName:"github GET /user",url:t,target:"github_user",headers:{authorization:`token ${R._t2}`,"content-type":"application/json",accept:"application/json"},signal:o.signal});if(!e.ok)throw i.end(),new Dt("Failed to get GitHub user",e);let r=await e.json();return i.end(),r}finally{clearTimeout(i)}}export{J as A,Z as B,_t as C,K as D,F as E,nt as F,U as G,Q as H,G as I,A as J,ut as K,D as L,gt as M,B as N,ht as O,pt as P,it as R,V as S,at as T,Ct as U,dt as V,Tt as W,S as X,R as Y,I as Z,yt as _,Ft as a,ct as b,Pt as c,$t as d,St as f,rt as g,c as h,Ht as i,W as j,Y as k,Nt as l,bt as m,Dt as n,qt as o,Et as p,P as q,Ut as r,jt as s,Lt as t,Mt as u,X as v,st as w,vt as x,ft as y,lt as z};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as s}from"./get-user-BfOVRifT.mjs";export{s as _s4};
|
package/dist/main.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{A as e,B as t,C as o,D as n,E as a,F as r,G as s,H as i,I as l,J as c,K as u,L as p,M as d,N as m,O as _,P as f,R as g,S as y,T as h,U as b,V as k,W as w,X as v,Y as x,Z as A,_ as $,a as T,b as S,c as O,d as I,f as q,g as N,h as P,i as j,j as C,k as E,l as R,m as D,n as M,o as H,p as F,q as B,r as J,s as L,t as U,u as K,v as W,w as z,x as G,y as V,z as Y}from"./get-user-BfOVRifT.mjs";import{defineCommand as Q,runMain as X}from"citty";import Z from"consola";import ee from"node:fs/promises";import te from"node:os";import{SpanKind as oe,SpanStatusCode as ne,context as ae,trace as re}from"@opentelemetry/api";import{Client as se}from"undici";import ie from"clipboardy";import le from"node:process";import{serve as ce}from"srvx";import ue from"tiny-invariant";import{execSync as pe}from"node:child_process";import{Hono as de}from"hono";import{cors as me}from"hono/cors";import{streamSSE as _e}from"hono/streaming";import{events as fe}from"fetch-event-stream";import{Tokenizer as ge,models as ye}from"ai-tokenizer";import*as he from"ai-tokenizer/encoding/claude";const be=async()=>{let e=`${j}/copilot_internal/v2/token`,t=x.timeoutMs,o=new AbortController,n=setTimeout(()=>o.abort(),t);try{let{response:t,span:n}=await b({spanName:"github GET /copilot_internal/v2/token",url:e,target:"copilot_token",headers:K(x),signal:o.signal});if(!t.ok)throw n.end(),new M("Failed to get Service token",t);let a=await t.json();return n.end(),a}finally{clearTimeout(n)}};const ke=e=>new Promise(t=>{setTimeout(t,e)});async function we(){x.models=await(async()=>{let e=`${O(x)}/models`,t=R(x),o=x.timeoutMs,n=new AbortController,a=setTimeout(()=>n.abort(),o);try{let{response:o,span:a}=await b({spanName:"copilot GET /models",url:e,target:"models",headers:t,signal:n.signal});if(!o.ok)throw a.end(),new M("Failed to get models",o);let r=await o.json();return a.setAttribute("copilot_api.models_count",r.data.length),a.end(),r}finally{clearTimeout(a)}})()}let ve,xe,Ae,$e=!1;const Te=async()=>{let{token:e,refresh_in:o}=await be();x._t1=e,Z.debug("Service token fetched successfully!"),x.showToken&&Z.info("Service token:",e);let n=async(e=5,o=1e3,n="scheduled")=>{if(!$e)return $e=!0,s.startActiveSpan("copilot_api.token.refresh",async a=>{let r=performance.now();a.setAttribute("copilot_api.token_refresh.reason",n),a.setAttribute("copilot_api.token_refresh.max_retries",e);try{for(let s=1;s<=e;s++)try{a.setAttribute("copilot_api.token_refresh.attempt",s),Z.debug(`Refreshing Service token (${n}, attempt ${s}/${e})`);let{token:o}=await be();return x._t1=o,Z.debug("Service token refreshed successfully"),x.showToken&&Z.info("Refreshed Service token:",o),a.setAttribute("copilot_api.token_refresh.success",!0),t.add(1,{reason:n,success:"true"}),k.record(performance.now()-r,{reason:n}),void G(P.INFO,"INFO",`Token refreshed successfully (${n})`,{"copilot_api.token_refresh.reason":n,"copilot_api.token_refresh.attempt":s})}catch(l){let c=s===e;if(Z.error(`Failed to refresh Service token (attempt ${s}/${e}):`,l),t.add(1,{reason:n,success:"false"}),c){Z.error("All refresh attempts failed. May be unavailable until next scheduled refresh.");let t=l instanceof Error?l:Error(String(l));return a.setAttribute("copilot_api.token_refresh.success",!1),a.setStatus({code:ne.ERROR,message:t.message}),a.recordException(t),i.add(1,{reason:n}),k.record(performance.now()-r,{reason:n}),void G(P.ERROR,"ERROR",`Token refresh failed after ${e} attempts (${n})`,{"copilot_api.token_refresh.reason":n,"copilot_api.token_refresh.attempts":e})}let u=o*2**(s-1);Z.debug(`Retrying token refresh in ${u}ms...`),await new Promise(e=>setTimeout(e,u))}}finally{a.end(),$e=!1}});Z.debug("Refresh already in progress, skipping")};ve=setInterval(()=>{n(5,1e3,"scheduled").catch(e=>{Z.error("Unexpected error in scheduled token refresh:",e)})},1e3*(o-60)),F.start(),xe=()=>{Z.debug("Network connectivity restored, attempting immediate token refresh"),n(3,500,"network-restored").catch(e=>{Z.error("Unexpected error in network-restored token refresh:",e)})},Ae=()=>{Z.debug("Network connectivity lost")},F.on("online",xe),F.on("offline",Ae)};async function Se(e){try{let t=await ee.readFile(v.GITHUB_TOKEN_PATH,"utf8");if(t&&!e?.force)return x._t2=t,x.showToken&&Z.info("Auth token:",t),void await Oe();Z.info("Authentication required");let o=await async function(){let e=new AbortController,t=x.timeoutMs,o=setTimeout(()=>{e.abort()},t);try{let t=await fetch(`${H}/login/device/code`,{method:"POST",headers:q(),body:JSON.stringify({client_id:L,scope:T}),signal:e.signal});if(!t.ok)throw new M("Failed to get device code",t);return await t.json()}finally{clearTimeout(o)}}();Z.debug("Device code response:",o),Z.info(`Please enter the code "${o.user_code}" in ${o.verification_uri}`);let n=await async function(e){let t=1e3*(e.interval+1);for(Z.debug(`Polling access token with interval of ${t}ms`);;){let o=new AbortController,n=x.timeoutMs,a=setTimeout(()=>{o.abort()},n);try{let n=await fetch(`${H}/login/oauth/access_token`,{method:"POST",headers:q(),body:JSON.stringify({client_id:L,device_code:e.device_code,grant_type:"urn:ietf:params:oauth:grant-type:device_code"}),signal:o.signal});if(!n.ok){await ke(t),Z.error("Failed to poll access token:",await n.text());continue}let a=await n.json();Z.debug("Polling access token response:",a);let{access_token:r}=a;if(r)return r;await ke(t)}catch(e){if(e instanceof Error&&"AbortError"===e.name){Z.error("Access token polling timed out"),await ke(t);continue}throw e}finally{clearTimeout(a)}}}(o);await(e=>ee.writeFile(v.GITHUB_TOKEN_PATH,e))(n),x._t2=n,x.showToken&&Z.info("Auth token:",n),await Oe()}catch(e){throw e instanceof M?(Z.error("Failed to get Auth token:",await e.response.json()),e):(Z.error("Failed to get Auth token:",e),e)}}async function Oe(){let e=await U();Z.debug(`Authenticated as ${e.login}`)}const Ie=Q({meta:{name:"auth",description:"Run authentication flow"},args:{verbose:{alias:"v",type:"boolean",default:!1,description:"Enable verbose logging"},"show-token":{type:"boolean",default:!1,description:"Show token on auth"}},run:({args:e})=>async function(e){e.verbose&&(Z.level=5,Z.info("Verbose logging enabled")),x.showToken=e.showToken,await A(),await Se({force:!0}),Z.success("Auth token written to",v.GITHUB_TOKEN_PATH)}({verbose:e.verbose,showToken:e["show-token"]})}),qe=async()=>{let e=`${j}/copilot_internal/user`,t=x.timeoutMs,o=new AbortController,n=setTimeout(()=>o.abort(),t);try{let{response:t,span:n}=await b({spanName:"github GET /copilot_internal/user",url:e,target:"usage",headers:K(x),signal:o.signal});if(!t.ok)throw n.end(),new M("Failed to get usage",t);let a=await t.json();return n.end(),a}finally{clearTimeout(n)}},Ne=Q({meta:{name:"check-usage",description:"Show current usage/quota information"},async run(){await A(),await Se();try{let e=await qe(),t=e.quota_snapshots.premium_interactions,o=t.entitlement,n=o-t.remaining,a=o>0?n/o*100:0,r=t.percent_remaining;function s(e,t){if(!t)return`${e}: N/A`;let o=t.entitlement,n=o-t.remaining,a=o>0?n/o*100:0,r=t.percent_remaining;return`${e}: ${n}/${o} used (${a.toFixed(1)}% used, ${r.toFixed(1)}% remaining)`}let i=`Premium: ${n}/${o} used (${a.toFixed(1)}% used, ${r.toFixed(1)}% remaining)`,l=s("Chat",e.quota_snapshots.chat),c=s("Completions",e.quota_snapshots.completions);Z.box(`Usage (plan: ${e.copilot_plan})\nQuota resets: ${e.quota_reset_date}\n\nQuotas:\n ${i}\n ${l}\n ${c}`)}catch(u){Z.error("Failed to fetch usage:",u),process.exit(1)}}});async function Pe(){try{let e=new URL("../package.json",import.meta.url).pathname,t=await ee.readFile(e);return JSON.parse(t.toString()).version}catch{return"unknown"}}function je(){let e=typeof Bun<"u";return{name:e?"bun":"node",version:e?Bun.version:process.version.slice(1),platform:te.platform(),arch:te.arch()}}async function Ce(){try{return!!(await ee.stat(v.GITHUB_TOKEN_PATH)).isFile()&&(await ee.readFile(v.GITHUB_TOKEN_PATH,"utf8")).trim().length>0}catch{return!1}}async function Ee(e){let t=await async function(){let[e,t]=await Promise.all([Pe(),Ce()]);return{version:e,runtime:je(),paths:{APP_DIR:v.APP_DIR,GITHUB_TOKEN_PATH:v.GITHUB_TOKEN_PATH},tokenExists:t}}();e.json?function(e){console.log(JSON.stringify(e,null,2))}(t):function(e){Z.info(`service debug\n\nVersion: ${e.version}\nRuntime: ${e.runtime.name} ${e.runtime.version} (${e.runtime.platform} ${e.runtime.arch})\n\nPaths:\n- APP_DIR: ${e.paths.APP_DIR}\n- GITHUB_TOKEN_PATH: ${e.paths.GITHUB_TOKEN_PATH}\n\nToken exists: ${e.tokenExists?"Yes":"No"}`)}(t)}const Re=Q({meta:{name:"debug",description:"Print debug information about the application"},args:{json:{type:"boolean",default:!1,description:"Output debug information as JSON"}},run:({args:e})=>Ee({json:e.json})}),De="copilot-api-node20",Me=`https://registry.npmjs.org/${De}/latest`,He=e=>`[1m${e}[0m`,Fe=e=>`[33m${e}[0m`;async function Be(){let e=new AbortController,t=setTimeout(()=>e.abort(),5e3);try{let t=await fetch(Me,{signal:e.signal});return t.ok?(await t.json()).version??null:null}catch{return null}finally{clearTimeout(t)}}function Je(e,t){let o=Math.max(0,t-function(e){return e.replaceAll(/\x1b\[[0-9;]*m/g,"").length}(e));return e+" ".repeat(o)}const Le=new Map,Ue=new Map,Ke=new Set;let We,ze,Ge;function Ve(e){return!e.closed&&!e.destroyed}function Ye(e){Z.debug(`Creating HTTP/2 client for ${e}`);let t=new se(e,{allowH2:!0,pipelining:0,keepAliveTimeout:6e4,initialWindowSize:4194304,connectionWindowSize:16777216});return Le.set(t,Date.now()),z.add(1,{event:"created",origin:e}),G(P.INFO,"INFO",`HTTP/2 client created for ${e}`,{"copilot_api.h2.event":"created","copilot_api.h2.origin":e}),t.on("connect",()=>{Z.debug(`HTTP/2 client connected to ${e}`)}),t.on("error",t=>{Z.debug(`HTTP/2 client error for ${e}:`,t.message)}),t.on("disconnect",(o,n,a)=>{Z.debug(`HTTP/2 client disconnected from ${e}:`,a.message),z.add(1,{event:"goaway",origin:e}),G(P.WARN,"WARN",`HTTP/2 client disconnected from ${e}: ${a.message}`,{"copilot_api.h2.event":"goaway","copilot_api.h2.origin":e,"copilot_api.h2.error":a.message}),Ue.delete(t),Ke.delete(t),Le.delete(t),Ve(t)&&t.close().catch(e=>{Z.debug("Error closing GOAWAY'd HTTP/2 client:",e)})}),t}function Qe(e){if(!x.connectivity.h2)return;We&&We!==e&&function(){for(let e of[...Ue.keys(),...Ke])Ve(e)&&e.close().catch(e=>{Z.debug("Error closing HTTP/2 pool entry:",e)});Ue.clear(),Ke.clear(),Le.clear()}(),We=e;let t=Date.now();for(let[o]of Ue)if(t-(Le.get(o)??0)>=6e5)Ue.delete(o),Le.delete(o),Ve(o)&&o.close().catch(e=>{Z.debug("Error closing rotated HTTP/2 client:",e)}),z.add(1,{event:"rotated",origin:e}),G(P.INFO,"INFO",`HTTP/2 client rotated for ${e} (max lifetime reached)`,{"copilot_api.h2.event":"rotated","copilot_api.h2.origin":e});else{if(Ve(o))return Ue.delete(o),Ke.add(o),o;Ue.delete(o),Le.delete(o)}let o=Ye(e);return Ke.add(o),o}function Xe(e){e&&Ke.delete(e)&&(Ve(e)?Ue.set(e,Date.now()):Le.delete(e))}function Ze(){Ge||(Ge=setInterval(()=>{!function(){let e=Date.now(),t=x.connectivity.h2Keepalive,o=Ue.size;for(let[n,a]of Ue)e-a<6e4||t&&o<=1||(Ue.delete(n),Le.delete(n),o--,Ve(n)&&n.close().catch(e=>{Z.debug("Error closing idle HTTP/2 client:",e)}),z.add(1,{event:"idle_reaped",origin:We??""}),G(P.INFO,"INFO",`HTTP/2 idle connection reaped for ${We}`,{"copilot_api.h2.event":"idle_reaped","copilot_api.h2.origin":We??""}))}()},3e4),Ge.unref())}function et(){ze||(Z.debug("Starting HTTP/2 keepalive (every 45s)"),ze=setInterval(()=>{(async function(){if(0===Ue.size&&0===Ke.size){if(We){let e=Ye(We);Ue.set(e,Date.now())}return}let e=[...Ue.keys()];await Promise.allSettled(e.map(async e=>{if(!Ve(e))return Ue.delete(e),void Le.delete(e);try{let{statusCode:t,body:o}=await e.request({path:"/models",method:"GET",headers:R(x)});await o.dump(),h.add(1,{result:"success"}),Z.debug(`HTTP/2 keepalive: GET /models → ${t}`),Ue.set(e,Date.now())}catch(t){h.add(1,{result:"error"}),Z.warn("HTTP/2 keepalive failed:",t instanceof Error?t.message:t),z.add(1,{event:"error",origin:We??""}),Ue.delete(e),Le.delete(e),Ve(e)&&e.close().catch(e=>{Z.debug("Error closing broken HTTP/2 client:",e)})}}))})().catch(e=>{Z.debug("Unexpected error in HTTP/2 keepalive:",e)})},45e3),ze.unref(),Ze())}function tt(e,t=""){let o,n=function(){let{platform:e,ppid:t,env:o}=le;if("win32"===e){try{if(pe(`wmic process get ParentProcessId,Name | findstr "${t}"`,{stdio:"pipe"}).toString().toLowerCase().includes("powershell.exe"))return"powershell"}catch{return"cmd"}return"cmd"}{let e=o.SHELL;if(e){if(e.endsWith("zsh"))return"zsh";if(e.endsWith("fish"))return"fish";if(e.endsWith("bash"))return"bash"}return"sh"}}(),a=Object.entries(e).filter(([,e])=>void 0!==e);switch(n){case"powershell":o=a.map(([e,t])=>`$env:${e} = ${t}`).join("; ");break;case"cmd":o=a.map(([e,t])=>`set ${e}=${t}`).join(" & ");break;case"fish":o=a.map(([e,t])=>`set -gx ${e} ${t}`).join("; ");break;default:{let e=a.map(([e,t])=>`${e}=${t}`).join(" ");o=a.length>0?`export ${e}`:"";break}}return o&&t?`${o}${"cmd"===n?" & ":" && "}${t}`:o||t}const ot=e=>`[1m${e}[0m`,nt=e=>`[2m${e}[0m`,at=e=>`[36m${e}[0m`,rt=e=>`[32m${e}[0m`,st=e=>`[33m${e}[0m`,it=e=>`[4m${e}[0m`,lt=(e,t)=>`]8;;${e}\\${t}]8;;\\`,ct="?utm_source=copilot-cli&utm_medium=terminal&utm_campaign=startup_banner",ut=nt(" ─────────────────────────────────────────────────────────────");function pt(e){return void 0===e?"":e>=1e6?`${(e/1e6).toFixed(0)}M`:`${(e/1e3).toFixed(0)}K`}const dt=[{title:"The 5-Hour Quota, Boris's Tweet, and What the Source Code Actually Reveals",teaser:"Claude Code's caching story — decoded from the source.",url:"https://barazany.dev/blog/claude-code-token-caching"},{title:"Claude Code's Compaction Engine: What the Source Code Actually Reveals",teaser:"What's actually running beneath every long session.",url:"https://barazany.dev/blog/claude-codes-compaction-engine"},{title:"We Were About to Buy an Automation Platform. We Already Had One.",teaser:"Governance spirals over n8n. The answer was already deployed.",url:"https://barazany.dev/blog/we-already-had-the-automation-platform"}];function mt(e){if(0===e.length)return[];let t=["",ut,` ${ot("BARAZANY.DEV")} ${nt("— Recent Posts")}`,ut,""];for(let[o,n]of e.entries()){let e=lt(`${n.url}${ct}`,ot(it(`[${o+1}]`)));t.push(` ${e} ${at(n.title)}`,` ${nt("→")} ${nt(n.teaser)}`,"")}return t.push(ut,` ${lt(`https://barazany.dev/blog${ct}`,"barazany.dev/blog")}`,ut),t}function _t(e){let t=[];x.connectivity.h2Keepalive?t.push("HTTP/2 keepalive"):x.connectivity.h2&&t.push("HTTP/2"),t.push(`timeout ${e.timeout/1e3}s`);let o=e.webSearch?`Tavily ${rt("✓")}`:nt("off"),n=["",` ${ot("COPILOT-API")} ${nt(`v${e.version}`)}`,ut,` ${nt("Runtime")} ${e.runtime.name} ${e.runtime.version} (${e.runtime.platform}-${e.runtime.arch})`,` ${nt("User")} ${e.user} ${nt("·")} ${e.accountType}`];return x._v1&&n.push(` ${nt("Client")} VSCode ${x._v1}`),n.push(` ${nt("Network")} ${t.join(nt(" · "))}`,` ${nt("Search")} ${o}`),e.clipboardCopied&&n.push(` ${nt("Clipboard")} Claude Code command ${rt("✓")}`),n.push(ut),n}function ft(e){if(!e.model&&!e.smallModel)return[];let t=["",` ${ot("Active")}`];if(e.model){let o=x.models?.data.find(t=>t.id===e.model),n=pt(o?.capabilities.limits?.max_context_window_tokens);t.push(` ${at(e.model.padEnd(32))} ${nt("ctx")} ${ot(n.padStart(5))} ${st("← main")}`)}if(e.smallModel){let o=x.models?.data.find(t=>t.id===e.smallModel),n=pt(o?.capabilities.limits?.max_context_window_tokens);t.push(` ${e.smallModel.padEnd(32)} ${nt("ctx")} ${n.padStart(5)} ${st("← small")}`)}return t}function gt(e){let t=[];for(let[o,n]of function(){let e=[],t=[],o=[],n=[];for(let a of x.models?.data??[]){let r=a.capabilities.limits?.max_context_window_tokens,s={id:a.id,ctx:r};a.id.startsWith("text-embedding")?n.push(s):"Anthropic"===a.vendor?e.push(s):"Google"===a.vendor?o.push(s):t.push(s)}return[["Claude",e],["OpenAI",t],["Gemini",o],["Embedding",n]]}())if(0!==n.length){t.push("",` ${ot(o)}`);for(let o of n){let n=o.id===e.model||o.id===e.smallModel,a=n?at("●"):nt("·"),r=n?at(o.id.padEnd(34)):o.id.padEnd(34),s=o.ctx?pt(o.ctx).padStart(5):"";t.push(` ${a} ${r} ${nt(s)}`)}}return t}function yt(e){let t=Math.floor(e/1e3),o=Math.floor(t/3600),n=Math.floor(t%3600/60);return o>0?`${o}h ${n}m`:n>0?`${n}m`:`${t}s`}function ht(e){(function(e){let{c:t,start:o,span:n}=e,a=t.get("requestData"),r=t.res.status,s=a?.model??"unknown",i=a?.streaming??!1,l=Date.now()-o;if(n.setAttribute("http.status_code",r),n.setAttribute("copilot_api.model",s),n.setAttribute("copilot_api.streaming",i),n.setAttribute("copilot_api.duration_ms",l),a?._d1&&n.setAttribute("copilot_api.copilot_duration_ms",a._d1),a?.tokenUsage){let e=a.tokenUsage;n.setAttribute("copilot_api.input_tokens",e.inputTokens),n.setAttribute("copilot_api.output_tokens",e.outputTokens),n.setAttribute("copilot_api.total_tokens",e.totalTokens),e.cachedTokens&&n.setAttribute("copilot_api.cached_tokens",e.cachedTokens),e.estimatedCost&&n.setAttribute("copilot_api.estimated_cost",e.estimatedCost)}t.res.headers.forEach((e,t)=>{let o=t.toLowerCase();D.has(o)||n.setAttribute(`http.response.header.${o}`,e)}),r>=400&&n.setStatus({code:ne.ERROR,message:`HTTP ${r}`}),n.end()})(e),function(e){let{c:t,start:o,method:a,path:s,endpointType:i,requestId:c}=e,u=Date.now()-o,p=t.get("requestData"),m=t.res.status,f=p?.model??"unknown",g=p?.streaming??!1,h={method:a,path:s,status_code:String(m),model:f,streaming:String(g),endpoint_type:i};if(l.add(1,h),r.record(u,h),m>=400&&y.add(1,{method:a,path:s,status_code:String(m),error_type:m>=500?"server_error":"client_error"}),p?.tokenUsage){let e=p.tokenUsage,t={model:f,endpoint_type:i};e.inputTokens&&(n.add(e.inputTokens,t),_.record(e.inputTokens,t)),e.outputTokens&&(C.add(e.outputTokens,t),d.record(e.outputTokens,t)),e.cachedTokens&&W.add(e.cachedTokens,{model:f})}!g&&p?.tokenUsage&&B.executeCompletion(c)}(e)}const bt=async()=>s.startActiveSpan("copilot_api.approval.await",async e=>{let t=performance.now();try{let o=await Z.prompt("Accept incoming request?",{type:"confirm"}),n=performance.now()-t;if(e.setAttribute("copilot_api.approval.wait_duration_ms",n),$.record(n),!o)throw e.setAttribute("copilot_api.approval.result","rejected"),N.add(1,{result:"rejected"}),new M("Request rejected",Response.json({message:"Request rejected"},{status:403}));e.setAttribute("copilot_api.approval.result","approved"),N.add(1,{result:"approved"})}finally{e.end()}}),kt=3e-6,wt=15e-6;function vt(e){let t=e.prompt_tokens||0,o=e.completion_tokens||0;return{inputTokens:t,outputTokens:o,totalTokens:e.total_tokens||t+o,estimatedCost:t*kt+o*wt,cachedTokens:e.prompt_tokens_details?.cached_tokens,acceptedPredictionTokens:e.completion_tokens_details?.accepted_prediction_tokens,rejectedPredictionTokens:e.completion_tokens_details?.rejected_prediction_tokens}}function xt(e,t){void 0!==t.prompt_tokens&&e.setAttribute("copilot_api.input_tokens",t.prompt_tokens),void 0!==t.completion_tokens&&e.setAttribute("copilot_api.output_tokens",t.completion_tokens),void 0!==t.total_tokens&&e.setAttribute("copilot_api.total_tokens",t.total_tokens)}const At=[{pattern:/haiku/i,family:"haiku"},{pattern:/sonnet[.-]?4[.-]6/i,family:"sonnet-4.6"},{pattern:/(sonnet-4[.-]5|[.-]?3[.-]5[.-]?sonnet|[.-]?3[.-]7[.-]?sonnet)/i,family:"sonnet-4.5"},{pattern:/sonnet-4(?![.-]5|[.-]6|[.-]1)/i,family:"sonnet-4"},{pattern:/opus[.-]?4[.-]6/i,family:"opus-4.6"},{pattern:/opus[.-]?4[.-]5/i,family:"opus-4.5"},{pattern:/opus/i,family:"opus"}],$t={haiku:"claude-haiku-4.5","sonnet-4.6":"claude-sonnet-4.6","sonnet-4.5":"claude-sonnet-4.5","sonnet-4":"claude-sonnet-4","opus-4.6":"claude-opus-4.6","opus-4.5":"claude-opus-4.5",opus:"claude-opus-4.5"};function Tt(e,t){let o=function(e){return e.startsWith("anthropic/")?e.slice(10):e}(e),[n,a]=function(e){let t=e.lastIndexOf("["),o=e.lastIndexOf("]");return-1!==t&&o===e.length-1&&o>t?[e.slice(0,t),e.slice(t+1,o)]:[e,null]}(o);if(t.includes(o))return o;if(a){let e=`${n}-${a}`.replaceAll(/(\d)-(\d)\b/g,"$1.$2");if(t.includes(e))return e}let r=function(e){for(let t of At)if(t.pattern.test(e))return t.family;return null}(n);if(!r)return null;let s=n.replace(/-\d{8}(?::.*)?$/,""),i=a?`-${a}`:"";for(let e of t){let t=e.replace(/-\d{8}(?::.*)?$/,""),o=`${s}${i}`.toLowerCase().replaceAll(/(\d)-(\d)\b/g,"$1.$2");if(t.toLowerCase().replaceAll(/(\d)-(\d)\b/g,"$1.$2")===o)return e}return function(e,t,o=null){let n=$t[e];if(!n)return null;if(o){let e=`${n}-${o}`;if(t.includes(e))return e}if(t.includes(n))return n;if("sonnet-4.5"===e)for(let e of["claude-3.5-sonnet"]){let n=o?`${e}-${o}`:e;if(t.includes(n))return n}return null}(r,t,a)}var St=class extends Error{statusCode;constructor(e,t=400){super(e),this.name="ModelValidationError",this.statusCode=t}};function Ot(t){if(!t||"string"!=typeof t)throw new St("Model name is required and must be a string");if(!x.models?.data)throw new St("Models not available. Please try again later.",503);let o=x.models.data.map(e=>e.id);if(o.includes(t))return t;let n=Tt(t,o);if(!n)throw e.add(1,{requested_model:t}),new St(`Invalid model: '${t}'. Available services: ${o.join(", ")}`);return n}async function It(e){if(void 0===e.rateLimitSeconds)return;let t=e.rateLimitSeconds;return s.startActiveSpan("copilot_api.rate_limit.check",async o=>{try{let n=Date.now();if(o.setAttribute("copilot_api.rate_limit.configured_seconds",t),!e.lastRequestTimestamp)return e.lastRequestTimestamp=n,void o.setAttribute("copilot_api.rate_limit.action","allowed");let a=(n-e.lastRequestTimestamp)/1e3;if(o.setAttribute("copilot_api.rate_limit.elapsed_seconds",a),a>t)return e.lastRequestTimestamp=n,void o.setAttribute("copilot_api.rate_limit.action","allowed");let r=Math.ceil(t-a);if(o.setAttribute("copilot_api.rate_limit.wait_seconds",r),!e.rateLimitWait)throw o.setAttribute("copilot_api.rate_limit.action","rejected"),m.add(1,{action:"rejected",source:"local"}),Z.warn(`Rate limit exceeded. Need to wait ${r} more seconds.`),new M("Rate limit exceeded",Response.json({message:"Rate limit exceeded"},{status:429}));let s=1e3*r;o.setAttribute("copilot_api.rate_limit.action","waited"),m.add(1,{action:"waited",source:"local"}),f.record(s,{source:"local"}),Z.warn(`Rate limit reached. Waiting ${r} seconds before proceeding...`),await ke(s),e.lastRequestTimestamp=n,Z.info("Rate limit wait completed, proceeding with request")}finally{o.end()}})}function qt(e){if("string"==typeof e)return function(e){let t=e,o=String.fromCodePoint(27),n=t.split(o);if(n.length>1){t=n[0];for(let e=1;e<n.length;e++){let a=n[e],r=a.match(/^\[[0-9;]*[a-z]/i);t+=r?a.slice(r[0].length):o+a}}return t.replaceAll(/[\u200B-\u200D\uFEFF]/g,"").replaceAll(/[\u2060-\u2064]/g,"").replaceAll(/[\u206A-\u206F]/g,"").replaceAll(/[\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/g,"").replaceAll(/[\uFFF0-\uFFFF]/g,"").replaceAll(/[\x00-\x08\v\f\x0E-\x1F]/g,"")}(e);if(Array.isArray(e))return e.map(e=>qt(e));if(e&&"object"==typeof e){let t={};for(let[o,n]of Object.entries(e))t[o]=qt(n);return t}return e}const Nt=async e=>{if(!x._t1)throw Error("Service token not found");let t=qt(e),o=t.messages.some(e=>"string"!=typeof e.content&&e.content?.some(e=>"image_url"===e.type)),n=t.messages.some(e=>["assistant","tool"].includes(e.role)),a={...R(x,o),"X-Initiator":n?"agent":"user"},r=O(x),s=`${r}/chat/completions`,i=Qe(r),l=x.timeoutMs,c=new AbortController,u=setTimeout(()=>c.abort(),l);try{let{statusCode:e,headers:r,body:u,span:p}=await w({spanName:"copilot POST /chat/completions",url:s,target:"chat_completions",headers:a,body:JSON.stringify(t),signal:c.signal,headersTimeout:l,bodyTimeout:3*l,extraAttributes:{"copilot_api.model":t.model,"copilot_api.streaming":!!t.stream,"copilot_api.timeout_ms":l,"copilot_api.has_tools":!!t.tools?.length,"copilot_api.tool_count":t.tools?.length??0,"copilot_api.message_count":t.messages.length,"copilot_api.max_tokens":t.max_tokens??0,"copilot_api.vision_enabled":o,"copilot_api.initiator":n?"agent":"user"},dispatcher:i}),d=new Response(u,{status:e,headers:r});if(!d.ok)throw p.end(),new M("Failed to create chat completions",d);if(t.stream)return{events:fe(d),span:p,release:()=>Xe(i)};let m=await d.json();return m.id&&p.setAttribute("copilot_api.response.id",m.id),m.usage&&xt(p,m.usage),p.end(),Xe(i),m}catch(e){throw Xe(i),e}finally{clearTimeout(u)}};function Pt(e){return s.startActiveSpan("copilot_api.model.validate",t=>{try{t.setAttribute("copilot_api.model.requested",e.model);let o=Ot(e.model);return t.setAttribute("copilot_api.model.normalized",o),o===e.model?(t.setAttribute("copilot_api.model.was_mapped",!1),e):(t.setAttribute("copilot_api.model.was_mapped",!0),E.add(1,{from_model:e.model,to_model:o}),Z.debug(`Normalized model from '${e.model}' to '${o}'`),{...e,model:o})}finally{t.end()}})}function jt(e,t){if(!e.data)return e;try{let o=JSON.parse(e.data);if(o.usage&&t(o.usage),void 0!==o.usage?.prompt_tokens_details?.cached_tokens)return{...e,data:JSON.stringify({...o,usage:{...o.usage,prompt_tokens_details:void 0}})}}catch{}return e}const Ct=e=>Object.hasOwn(e,"choices"),Et=new de;Et.post("/",async e=>{try{return await async function(e){await It(x);let t=await e.req.json();Z.debug("Request payload:",JSON.stringify(t).slice(-400));try{t=Pt(t)}catch(t){if(t instanceof St)return e.json({error:{message:t.message,type:"invalid_request_error",code:"invalid_model"}},t.statusCode);throw t}if(e.set("requestData",{model:t.model,streaming:!!t.stream}),x.manualApprove&&await bt(),(e=>null==e)(t.max_tokens)){let e=x.models?.data.find(e=>e.id===t.model);t={...t,max_tokens:e?.capabilities.limits?.max_output_tokens},Z.debug("Set max_tokens to:",JSON.stringify(t.max_tokens))}let o=performance.now(),n=await Nt(t),a=performance.now()-o;if(S.record(a,{model:t.model,target:"chat_completions",streaming:String(!!t.stream)}),Ct(n)){let t=e.get("requestData")||{};return n.usage&&(t.tokenUsage=vt(n.usage)),t._d1=a,e.set("requestData",t),Z.debug("Non-streaming response:",JSON.stringify(n)),e.json(n)}let{events:r,span:s,release:i}=n;return _e(e,async o=>{let n={value:null},l=0,c=performance.now();try{try{for await(let s of r){let r=s;s.data&&"[DONE]"!==s.data&&(l++,g.add(1,{model:t.model,endpoint_type:"openai"}),r=jt(s,t=>{n.value=t;let o=e.get("requestData")||{};o.tokenUsage=vt(t),o._d1=a,e.set("requestData",o)})),await o.writeSSE(r)}let s=performance.now()-c,i={model:t.model,endpoint_type:"openai"};if(Y.record(s,i),V.record(l,i),n.value){let t=e.get("requestData")||{};t.tokenUsage||(t.tokenUsage=vt(n.value),t._d1=a,e.set("requestData",t))}}finally{n.value&&xt(s,n.value),s.end(),i()}let u=e.get("requestId");u&&B.executeCompletion(u)}finally{e.get("resolveStreamComplete")?.()}})}(e)}catch(t){return await J(e,t)}});const Rt=new de;Rt.post("/",async e=>{try{let t=await e.req.json();try{Ot(t.model)}catch(t){if(t instanceof St)return e.json({error:{message:t.message,type:"invalid_request_error",code:"invalid_model"}},t.statusCode);throw t}e.set("requestData",{model:t.model});let o=performance.now(),n=await(async e=>{if(!x._t1)throw Error("Service token not found");let t=`${O(x)}/embeddings`,o=R(x),n=x.timeoutMs,a=new AbortController,r=setTimeout(()=>a.abort(),n);try{let{response:n,span:r}=await b({spanName:"copilot POST /embeddings",url:t,target:"embeddings",method:"POST",headers:o,body:JSON.stringify(e),signal:a.signal,extraAttributes:{"copilot_api.model":e.model,"copilot_api.input_count":Array.isArray(e.input)?e.input.length:1}});if(!n.ok)throw r.end(),new M("Failed to create embeddings",n);let s=await n.json();return r.end(),s}finally{clearTimeout(r)}})(t),a=performance.now()-o;S.record(a,{model:t.model,target:"embeddings",streaming:"false"});let r=e.get("requestData")||{};return r.tokenUsage=vt(n.usage),r._d1=a,e.set("requestData",r),e.json(n)}catch(t){return await J(e,t)}});const Dt=new ge(he),Mt={...ye["anthropic/claude-sonnet-4"].tokens,baseOverhead:4,perTool:27};function Ht(e){return Dt.encode(e).length}function Ft(e){let t=0;for(let o of e)switch(o.type){case"text":t+=Ht(o.text)*Mt.contentMultiplier;break;case"tool_use":t+=Ht(o.name+JSON.stringify(o.input))*Mt.contentMultiplier;break;case"tool_result":o.content&&(t+=Ht("string"==typeof o.content?o.content:JSON.stringify(o.content))*Mt.contentMultiplier);break;case"thinking":t+=Ht(o.thinking)*Mt.contentMultiplier;break;case"image":t+=1600}return t}function Bt(e){let t=0,o=e.properties;if(!o)return t;let n=Object.entries(o);for(let[e,[o,a]]of n.entries()){if(t+=0===e?Mt.perFirstProp:Mt.perAdditionalProp,t+=Ht(o),a.description&&(t+=Mt.perPropDesc+Ht(a.description)),a.enum&&Array.isArray(a.enum)){t+=Mt.perEnum;for(let e of a.enum)t+=Ht(String(e))}if("object"===a.type&&a.properties&&(t+=Mt.perNestedObject,t+=Bt(a)),"array"===a.type&&a.items){let e=a.items;"object"===e.type&&e.properties&&(t+=Mt.perArrayOfObjects,t+=Bt(e))}}return t}const Jt=async e=>{if(!x._t1)throw Error("Service token not found");let t=qt(e),o={...R(x),"X-Initiator":"agent"},n=O(x),a=`${n}/responses`,r=Qe(n),s=x.timeoutMs,i=new AbortController,l=setTimeout(()=>i.abort(),s);try{let{statusCode:e,headers:n,body:l,span:c}=await w({spanName:"copilot POST /responses",url:a,target:"responses",headers:o,body:JSON.stringify(t),signal:i.signal,headersTimeout:s,bodyTimeout:3*s,extraAttributes:{"copilot_api.model":t.model,"copilot_api.streaming":!!t.stream,"copilot_api.timeout_ms":s,"copilot_api.has_tools":!!t.tools?.length,"copilot_api.tool_count":t.tools?.length??0,"copilot_api.max_output_tokens":t.max_output_tokens??0,"copilot_api.api_type":"responses"},dispatcher:r}),u=new Response(l,{status:e,headers:n});if(!u.ok)throw c.end(),new M("Failed to create responses",u);if(t.stream)return{events:fe(u),span:c};let p=await u.json();return p.id&&c.setAttribute("copilot_api.response.id",p.id),p.usage&&xt(c,{prompt_tokens:p.usage.input_tokens,completion_tokens:p.usage.output_tokens,total_tokens:p.usage.total_tokens}),c.end(),p}finally{clearTimeout(l)}};function Lt(e){return null===e?null:{stop:"end_turn",length:"max_tokens",tool_calls:"tool_use",content_filter:"end_turn"}[e]}function Ut(e,t){let o=function(e){return e?"string"==typeof e?[{role:"system",content:Kt(e)}]:[{role:"system",content:Kt(e.map(e=>e.text).join("\n\n"))}]:[]}(t),n=e.flatMap(e=>"user"===e.role?function(e){let t=[];if(Array.isArray(e.content)){let o=e.content.filter(e=>"tool_result"===e.type),n=e.content.filter(e=>"tool_result"!==e.type);for(let e of o)t.push({role:"tool",tool_call_id:e.tool_use_id,content:Wt(e.content)});n.length>0&&t.push({role:"user",content:Wt(n)})}else t.push({role:"user",content:Wt(e.content)});return t}(e):function(e){if(!Array.isArray(e.content))return[{role:"assistant",content:Wt(e.content)}];let t=e.content.filter(e=>"tool_use"===e.type),o=e.content.filter(e=>"text"===e.type),n=e.content.filter(e=>"thinking"===e.type),a=[...o.map(e=>e.text),...n.map(e=>e.thinking)].join("\n\n");return t.length>0?[{role:"assistant",content:a||null,tool_calls:t.map(e=>({id:e.id,type:"function",function:{name:e.name,arguments:JSON.stringify(e.input)}}))}]:[{role:"assistant",content:Wt(e.content)}]}(e));return[...o,...n]}function Kt(e){return e.startsWith("x-anthropic-billing-header")?e.replace(/^x-_an1-billing-header:[^\n]*\n+/,""):e}function Wt(e){if("string"==typeof e)return e;if(!Array.isArray(e))return null;if(!e.some(e=>"image"===e.type))return e.filter(e=>"text"===e.type||"thinking"===e.type).map(e=>"text"===e.type?e.text:e.thinking).join("\n\n");let t=[];for(let o of e)switch(o.type){case"text":t.push({type:"text",text:o.text});break;case"thinking":t.push({type:"text",text:o.thinking});break;case"image":t.push({type:"image_url",image_url:{url:`data:${o.source.media_type};base64,${o.source.data}`}})}return t}function zt(e){if(e)return e.map(e=>({type:"function",function:{name:e.name,description:e.description,parameters:e.input_schema}}))}function Gt(e){if(e)switch(e.type){case"auto":return"auto";case"any":return"required";case"tool":return e.name?{type:"function",function:{name:e.name}}:void 0;case"none":return"none";default:return}}function Vt(e){return"string"==typeof e?[{type:"text",text:e}]:Array.isArray(e)?e.filter(e=>"text"===e.type).map(e=>({type:"text",text:e.text})):[]}function Yt(e){return e?e.map(e=>({type:"tool_use",id:e.id,name:e.function.name,input:JSON.parse(e.function.arguments)})):[]}function Qt(e){let t={model:e.model,input:Xt(e.messages),max_output_tokens:Math.max(e.max_tokens,16),stream:e.stream,temperature:e.temperature,top_p:e.top_p,store:!1,user:e.metadata?.user_id?.slice(0,64)},o=function(e){return e?function(e){return e.startsWith("x-anthropic-billing-header")?e.replace(/^x-_an1-billing-header:[^\n]*\n+/,""):e}("string"==typeof e?e:e.map(e=>e.text).join("\n\n")):null}(e.system);if(o&&(t.instructions=o),e.tools?.length&&(t.tools=e.tools.map(e=>({type:"function",name:e.name,description:e.description,parameters:e.input_schema}))),e.tool_choice&&(t.tool_choice=function(e){switch(e.type){case"auto":return"auto";case"any":return"required";case"none":return"none";case"tool":return e.name?{type:"function",name:e.name}:void 0;default:return}}(e.tool_choice)),"enabled"===e.thinking?.type&&e.thinking.budget_tokens){let o=e.thinking.budget_tokens,n="high";o<5e3?n="low":o<2e4&&(n="medium"),t.reasoning={effort:n}}return t}function Xt(e){let t=[];for(let o of e)"user"===o.role?t.push(...Zt(o)):t.push(...to(o));return t}function Zt(e){if("string"==typeof e.content)return[{type:"message",role:"user",content:e.content}];let t=[],o=e.content.filter(e=>"tool_result"===e.type),n=e.content.filter(e=>"tool_result"!==e.type);for(let e of o)t.push(eo(e));if(n.length>0)if(n.some(e=>"image"===e.type)){let e=[];for(let t of n)"text"===t.type?e.push({type:"input_text",text:t.text}):e.push({type:"input_image",image_url:`data:${t.source.media_type};base64,${t.source.data}`});t.push({type:"message",role:"user",content:e})}else{let e=n.filter(e=>"text"===e.type).map(e=>e.text).join("\n\n");e&&t.push({type:"message",role:"user",content:e})}return t}function eo(e){let t;return t="string"==typeof e.content?e.content:Array.isArray(e.content)?e.content.filter(e=>"text"===e.type).map(e=>e.text).join("\n"):"",e.is_error&&(t=`[ERROR] ${t}`),{type:"function_call_output",call_id:e.tool_use_id,output:t}}function to(e){if("string"==typeof e.content)return[{type:"message",role:"assistant",content:e.content}];let t=[],o=e.content.filter(e=>"text"===e.type),n=e.content.filter(e=>"thinking"===e.type),a=e.content.filter(e=>"tool_use"===e.type),r=[...o.map(e=>e.text),...n.map(e=>e.thinking)].join("\n\n");r&&t.push({type:"message",role:"assistant",content:r});for(let e of a)t.push({type:"function_call",call_id:e.id,name:e.name,arguments:JSON.stringify(e.input)});return t}function oo(e,t){if(t)return"tool_use";switch(e){case"completed":case"cancelled":case"failed":return"end_turn";case"incomplete":return"max_tokens";default:return null}}function no(e,t){e.contentBlockOpen&&=(t.push({type:"content_block_stop",index:e.contentBlockIndex}),e.contentBlockIndex++,!1)}function ao(e,t,o){e.messageStartSent||=(e.responseId=o?.responseId??e.responseId,e.model=o?.model??e.model,t.push({type:"message_start",message:{id:e.responseId,type:"message",role:"assistant",content:[],model:e.model,stop_reason:null,stop_sequence:null,usage:{input_tokens:0,output_tokens:0}}}),!0)}function ro(e,t){let o=[];switch(e.type){case"response.created":ao(t,o,{responseId:e.response.id,model:e.response.model});break;case"response.in_progress":case"response.output_text.done":case"response.function_call_arguments.done":case"response.refusal.done":case"response.reasoning_summary_text.delta":case"response.reasoning_summary_text.done":default:break;case"response.output_item.added":if("function_call"===e.item.type){ao(t,o),no(t,o);let n=e.item;t.toolCalls[e.output_index]={call_id:n.call_id,name:n.name,_bi1:t.contentBlockIndex},o.push({type:"content_block_start",index:t.contentBlockIndex,content_block:{type:"tool_use",id:n.call_id,name:n.name,input:{}}}),t.contentBlockOpen=!0}break;case"response.content_part.added":ao(t,o),no(t,o),o.push({type:"content_block_start",index:t.contentBlockIndex,content_block:{type:"text",text:""}}),t.contentBlockOpen=!0;break;case"response.output_text.delta":o.push({type:"content_block_delta",index:t.contentBlockIndex,delta:{type:"text_delta",text:e.delta}});break;case"response.content_part.done":no(t,o);break;case"response.function_call_arguments.delta":{let n=t.toolCalls[e.output_index];n&&o.push({type:"content_block_delta",index:n._bi1,delta:{type:"input_json_delta",partial_json:e.delta}});break}case"response.output_item.done":if("function_call"===e.item.type){let n=t.toolCalls[e.output_index];n&&t.contentBlockOpen&&(o.push({type:"content_block_stop",index:n._bi1}),t.contentBlockIndex++,t.contentBlockOpen=!1)}break;case"response.completed":{no(t,o);let n=e.response.output.some(e=>"function_call"===e.type),a=e.response.usage;o.push({type:"message_delta",delta:{stop_reason:oo(e.response.status,n),stop_sequence:null},usage:{input_tokens:a?.input_tokens??0,output_tokens:a?.output_tokens??0}},{type:"message_stop"});break}case"response.incomplete":{ao(t,o),no(t,o);let n=e.response.usage;o.push({type:"message_delta",delta:{stop_reason:"max_tokens",stop_sequence:null},usage:{input_tokens:n?.input_tokens??0,output_tokens:n?.output_tokens??0}},{type:"message_stop"});break}case"response.failed":ao(t,o),no(t,o),o.push({type:"error",error:{type:e.response.error?.code??"api_error",message:e.response.error?.message??"Response generation failed"}});break;case"response.cancelled":ao(t,o),no(t,o),o.push({type:"message_delta",delta:{stop_reason:"end_turn",stop_sequence:null},usage:{input_tokens:0,output_tokens:0}},{type:"message_stop"});break;case"response.refusal.delta":ao(t,o),t.contentBlockOpen||=(o.push({type:"content_block_start",index:t.contentBlockIndex,content_block:{type:"text",text:""}}),!0),o.push({type:"content_block_delta",index:t.contentBlockIndex,delta:{type:"text_delta",text:e.delta}})}return o}function so(e,t){let o=[];if(0===e.choices.length)return o;let n=e.choices[0],{delta:a}=n;if(t.messageStartSent||=(o.push({type:"message_start",message:{id:e.id,type:"message",role:"assistant",content:[],model:e.model,stop_reason:null,stop_sequence:null,usage:{input_tokens:e.usage?.prompt_tokens??0,output_tokens:0}}}),!0),a.content&&(function(e){return!!e.contentBlockOpen&&Object.values(e.toolCalls).some(t=>t._bi1===e.contentBlockIndex)}(t)&&(o.push({type:"content_block_stop",index:t.contentBlockIndex}),t.contentBlockIndex++,t.contentBlockOpen=!1),t.contentBlockOpen||=(o.push({type:"content_block_start",index:t.contentBlockIndex,content_block:{type:"text",text:""}}),!0),o.push({type:"content_block_delta",index:t.contentBlockIndex,delta:{type:"text_delta",text:a.content}})),a.tool_calls)for(let e of a.tool_calls){if(e.id&&e.function?.name){t.contentBlockOpen&&=(o.push({type:"content_block_stop",index:t.contentBlockIndex}),t.contentBlockIndex++,!1);let n=t.contentBlockIndex;t.toolCalls[e.index]={id:e.id,name:e.function.name,_bi1:n},o.push({type:"content_block_start",index:n,content_block:{type:"tool_use",id:e.id,name:e.function.name,input:{}}}),t.contentBlockOpen=!0}if(e.function?.arguments){let n=t.toolCalls[e.index];n&&o.push({type:"content_block_delta",index:n._bi1,delta:{type:"input_json_delta",partial_json:e.function.arguments}})}}return n.finish_reason&&(t.contentBlockOpen&&=(o.push({type:"content_block_stop",index:t.contentBlockIndex}),!1),o.push({type:"message_delta",delta:{stop_reason:Lt(n.finish_reason),stop_sequence:null},usage:{input_tokens:e.usage?.prompt_tokens??0,output_tokens:e.usage?.completion_tokens??0}},{type:"message_stop"})),o}async function io(e,t,o){let n={query:t,max_results:o?.maxResults??5};o?.includeDomains?.length&&(n.include_domains=o.includeDomains),o?.excludeDomains?.length&&(n.exclude_domains=o.excludeDomains),Z.debug("Tavily search request:",JSON.stringify(n));let a=await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(n)});if(!a.ok){let e=await a.text();throw Z.error(`Tavily API error (${a.status}):`,e),Error(`Tavily API error: ${a.status} ${e}`)}let r=await a.json();return Z.debug(`Tavily returned ${r.results.length} results`),r.results}function lo(){let e="";for(let t=0;t<24;t++)e+="abcdefghijklmnopqrstuvwxyz0123456789"[Math.floor(36*Math.random())];return e}async function co(e,t){let o=function(e){let t,o=e.messages[0];if(!o||"user"!==o.role)return null;if("string"==typeof o.content)t=o.content;else{if(!Array.isArray(o.content))return null;{let e=o.content.find(e=>"text"===e.type);if(!e)return null;t=e.text}}return t.startsWith("Perform a web search for the query: ")?t.slice(36).trim():t.trim()||null}(t);if(!o)return e.json({type:"error",error:{type:"invalid_request_error",message:"Could not extract search query from web search request"}},400);let n=function(e){let t=e.tools?.[0];return{maxResults:"number"==typeof t?.max_uses?t.max_uses:5,allowedDomains:t?.allowed_domains,blockedDomains:t?.blocked_domains}}(t);Z.info(`Web search intercepted: "${o}"`);let a=[];try{let e=x.tavilyApiKey;if(!e)throw Error("No Tavily API key configured");a=(await io(e,o,{maxResults:Math.min(n.maxResults,10),includeDomains:n.allowedDomains,excludeDomains:n.blockedDomains})).map(e=>({type:"web_search_result",url:e.url,title:e.title,encrypted_content:Buffer.from(e.content).toString("base64"),page_age:null}))}catch(e){Z.error("Tavily search failed:",e)}let r={query:o,results:a,model:t.model};if(!t.stream)return e.json(function(e){let{query:t,results:o,model:n}=e,a=`srvtoolu_${lo()}`,r=[{type:"text",text:"I'll search for that."},{type:"server_tool_use",id:a,name:"web_search",input:{query:t}},{type:"web_search_tool_result",tool_use_id:a,content:o}];return{id:`msg_tavily_${lo()}`,type:"message",role:"assistant",model:n,content:r,stop_reason:"end_turn",stop_sequence:null,usage:{input_tokens:0,output_tokens:0}}}(r));let s=function(e){let{query:t,results:o,model:n}=e,a=`srvtoolu_${lo()}`,r=`msg_tavily_${lo()}`,s=[];return s.push({type:"message_start",message:{id:r,type:"message",role:"assistant",content:[],model:n,stop_reason:null,stop_sequence:null,usage:{input_tokens:0,output_tokens:0}}},{type:"content_block_start",index:0,content_block:{type:"text",text:""}},{type:"content_block_delta",index:0,delta:{type:"text_delta",text:"I'll search for that."}},{type:"content_block_stop",index:0},{type:"content_block_start",index:1,content_block:{type:"server_tool_use",id:a,name:"web_search",input:{}}},{type:"content_block_delta",index:1,delta:{type:"input_json_delta",partial_json:JSON.stringify({query:t})}},{type:"content_block_stop",index:1},{type:"content_block_start",index:2,content_block:{type:"web_search_tool_result",tool_use_id:a,content:o}},{type:"content_block_stop",index:2},{type:"message_delta",delta:{stop_reason:"end_turn",stop_sequence:null},usage:{output_tokens:0}},{type:"message_stop"}),s}(r);return _e(e,async e=>{for(let t of s)await e.writeSSE({event:t.type,data:JSON.stringify(t)})})}async function uo(e){let t=await e.req.json();if(function(e){let t=e.tools;if(!t||1!==t.length)return!1;let o=t[0].type;return"string"==typeof o&&o.startsWith("web_search")}(t))return co(e,t);await It(x),Z.debug("Anthropic request payload:",JSON.stringify(t));let o=e.req.header("anthropic-beta")??"",n=/context-1m/i.test(o);if(n&&/claude/i.test(t.model)){let e=t.model;t={...t,model:`${t.model}-1m`},Z.debug(`Detected context-1m beta flag, rewriting model: '${e}' → '${t.model}'`)}let a=function(e,t){return s.startActiveSpan("copilot_api.model.validate",o=>{try{o.setAttribute("copilot_api.model.requested",t.model);let e=Ot(t.model);return o.setAttribute("copilot_api.model.normalized",e),e===t.model?(o.setAttribute("copilot_api.model.was_mapped",!1),t):(o.setAttribute("copilot_api.model.was_mapped",!0),E.add(1,{from_model:t.model,to_model:e}),Z.debug(`Model mapping: '${t.model}' → '${e}'`),{...t,model:e})}catch(t){if(t instanceof St)return e.json({type:"error",error:{type:"invalid_request_error",message:t.message}},t.statusCode),null;throw t}finally{o.end()}})}(e,t);if(!a)return;if(t=a,function(e){return/gpt-[\d.]+-codex/i.test(e)}(t.model))return async function(e,t){let o=performance.now(),n=s.startActiveSpan("copilot_api.translate.anthropic_to_responses",e=>{try{return e.setAttribute("copilot_api.translation.direction","anthropic_to_responses"),e.setAttribute("copilot_api.translation.message_count",t.messages.length),Qt(t)}finally{e.end()}});u.record(performance.now()-o,{direction:"anthropic_to_responses"}),Z.debug("Translated Responses API payload:",JSON.stringify(n)),e.set("requestData",{model:n.model,streaming:!!n.stream}),x.manualApprove&&await bt();let a=performance.now(),r=await Jt(n),i=performance.now()-a;if(S.record(i,{model:n.model,target:"responses",streaming:String(!!n.stream)}),_o(r)){let t=e.get("requestData")||{};if(r.usage&&(t.tokenUsage=vt({prompt_tokens:r.usage.input_tokens,completion_tokens:r.usage.output_tokens,total_tokens:r.usage.total_tokens})),t._d1=i,e.set("requestData",t),Z.debug("Non-streaming Responses API response:",JSON.stringify(r).slice(-400)),"failed"===r.status)return e.json({type:"error",error:{type:r.error?.code??"api_error",message:r.error?.message??"Response generation failed"}},500);let o=performance.now(),n=s.startActiveSpan("copilot_api.translate.responses_to_anthropic",e=>{try{return e.setAttribute("copilot_api.translation.direction","responses_to_anthropic"),function(e){let t=[],o=!1;for(let n of e.output)if("message"===n.type)for(let e of n.content)e.text&&t.push({type:"text",text:e.text});else if("function_call"===n.type){o=!0;let e={};try{e=JSON.parse(n.arguments)}catch{}t.push({type:"tool_use",id:n.call_id,name:n.name,input:e})}return{id:e.id,type:"message",role:"assistant",model:e.model,content:t,stop_reason:oo(e.status,o),stop_sequence:null,usage:{input_tokens:e.usage?.input_tokens??0,output_tokens:e.usage?.output_tokens??0}}}(r)}finally{e.end()}});return u.record(performance.now()-o,{direction:"responses_to_anthropic"}),e.json(n)}Z.debug("Streaming Responses API response");let{events:l,span:c}=r;return _e(e,async t=>{let o=null,a=0,r=performance.now(),s={messageStartSent:!1,contentBlockIndex:0,contentBlockOpen:!1,responseId:"",model:"",toolCalls:{}};try{try{for await(let r of l){if(Z.debug("Responses API raw stream event:",JSON.stringify(r)),!r.data)continue;let l;try{l=JSON.parse(r.data)}catch{continue}a++,g.add(1,{model:n.model,endpoint_type:"responses"});let c=po(l);if(c){o=c;let t=e.get("requestData")||{};t.tokenUsage=vt(o),t._d1=i,e.set("requestData",t)}let u=ro(l,s);for(let e of u)Z.debug("Translated Anthropic event:",JSON.stringify(e)),await t.writeSSE({event:e.type,data:JSON.stringify(e)})}let c=performance.now()-r,u={model:n.model,endpoint_type:"responses"};Y.record(c,u),V.record(a,u)}finally{o&&xt(c,o),c.end()}let u=e.get("requestId");u&&B.executeCompletion(u)}finally{e.get("resolveStreamComplete")?.()}})}(e,t);let r=performance.now(),i=s.startActiveSpan("copilot_api.translate.anthropic_to_openai",e=>{try{e.setAttribute("copilot_api.translation.direction","anthropic_to_openai"),e.setAttribute("copilot_api.translation.message_count",t.messages.length),e.setAttribute("copilot_api.translation.has_tools",!!t.tools?.length),e.setAttribute("copilot_api.translation.has_system",!!t.system),e.setAttribute("copilot_api.translation.context_1m_beta",n);let o=t.messages.some(e=>Array.isArray(e.content)&&e.content.some(e=>"image"===e.type)),a=t.messages.some(e=>Array.isArray(e.content)&&e.content.some(e=>"thinking"===e.type));return e.setAttribute("copilot_api.translation.has_images",o),e.setAttribute("copilot_api.translation.has_thinking",a),function(e){return{model:e.model,messages:Ut(e.messages,e.system),max_tokens:e.max_tokens,stop:e.stop_sequences,stream:e.stream,temperature:e.temperature,top_p:e.top_p,user:e.metadata?.user_id,tools:zt(e.tools),tool_choice:Gt(e.tool_choice)}}(t)}finally{e.end()}});u.record(performance.now()-r,{direction:"anthropic_to_openai"}),Z.debug("Translated OpenAI request payload:",JSON.stringify(i)),e.set("requestData",{model:i.model,streaming:!!i.stream});let l=performance.now();x.manualApprove&&await bt();let c=await Nt(i),p=performance.now()-l;if(S.record(p,{model:i.model,target:"chat_completions",streaming:String(!!i.stream)}),mo(c)){let t=e.get("requestData")||{};c.usage&&(t.tokenUsage=vt(c.usage)),t._d1=p,e.set("requestData",t),Z.debug("Non-streaming response:",JSON.stringify(c).slice(-400));let o=performance.now(),n=s.startActiveSpan("copilot_api.translate.openai_to_anthropic",e=>{try{e.setAttribute("copilot_api.translation.direction","openai_to_anthropic");let t=function(e){let t=[],o=[],n=null;n=e.choices[0]?.finish_reason??n;for(let a of e.choices){let e=Vt(a.message.content),r=Yt(a.message.tool_calls);t.push(...e),o.push(...r),("tool_calls"===a.finish_reason||"stop"===n)&&(n=a.finish_reason)}return{id:e.id,type:"message",role:"assistant",model:e.model,content:[...t,...o],stop_reason:Lt(n),stop_sequence:null,usage:{input_tokens:e.usage?.prompt_tokens??0,output_tokens:e.usage?.completion_tokens??0}}}(c);return e.setAttribute("copilot_api.translation.content_blocks",t.content.length),e.setAttribute("copilot_api.translation.stop_reason",t.stop_reason??"null"),e.setAttribute("copilot_api.translation.has_tool_use",t.content.some(e=>"tool_use"===e.type)),t}finally{e.end()}});return u.record(performance.now()-o,{direction:"openai_to_anthropic"}),Z.debug("Translated Anthropic response:",JSON.stringify(n)),e.json(n)}Z.debug("Streaming response from service");let{events:d,span:m,release:_}=c;return _e(e,async t=>{let o=null,n=0,a=performance.now(),r={messageStartSent:!1,contentBlockIndex:0,contentBlockOpen:!1,toolCalls:{}};try{try{for await(let a of d){if(Z.debug("Raw stream event:",JSON.stringify(a)),"[DONE]"===a.data)break;if(!a.data)continue;let s=JSON.parse(a.data);if(n++,g.add(1,{model:i.model,endpoint_type:"anthropic"}),s.usage){o=s.usage;let t=e.get("requestData")||{};t.tokenUsage=vt(o),t._d1=p,e.set("requestData",t)}let l=so(s,r);for(let e of l)Z.debug("Translated Anthropic event:",JSON.stringify(e)),await t.writeSSE({event:e.type,data:JSON.stringify(e)})}let s=performance.now()-a,l={model:i.model,endpoint_type:"anthropic"};if(Y.record(s,l),V.record(n,l),o){let t=e.get("requestData")||{};t.tokenUsage||(t.tokenUsage=vt(o),t._d1=p,e.set("requestData",t))}}finally{o&&xt(m,o),m.end(),_()}let s=e.get("requestId");s&&B.executeCompletion(s)}finally{e.get("resolveStreamComplete")?.()}})}function po(e){if("response.completed"!==e.type&&"response.incomplete"!==e.type)return null;let t=e.response.usage;return t?{prompt_tokens:t.input_tokens,completion_tokens:t.output_tokens,total_tokens:t.total_tokens}:null}const mo=e=>Object.hasOwn(e,"choices"),_o=e=>Object.hasOwn(e,"output");const fo=new de;fo.post("/",async e=>{try{return await uo(e)}catch(t){return await J(e,t)}});const go=new de;function yo(e){return s.startActiveSpan("copilot_api.model.validate",t=>{try{t.setAttribute("copilot_api.model.requested",e.model);let o=Ot(e.model);return t.setAttribute("copilot_api.model.normalized",o),o===e.model?(t.setAttribute("copilot_api.model.was_mapped",!1),e):(t.setAttribute("copilot_api.model.was_mapped",!0),E.add(1,{from_model:e.model,to_model:o}),Z.debug(`Normalized model from '${e.model}' to '${o}'`),{...e,model:o})}finally{t.end()}})}function ho(e,t){let o=function(e){try{let t=JSON.parse(e);if(("response.completed"===t.type||"response.incomplete"===t.type)&&t.response?.usage){let e=t.response.usage;return{prompt_tokens:e.input_tokens,completion_tokens:e.output_tokens,total_tokens:e.total_tokens}}}catch{}return null}(e);if(!o)return;t.usageRef.value=o;let n=t.c.get("requestData")||{};n.tokenUsage=vt(o),n._d1=t._d1,t.c.set("requestData",n)}go.get("/",async e=>{try{x.models||await we();let t=x.models?.data.map(e=>({id:e.id,object:"model",type:"model",created:0,created_at:new Date(0).toISOString(),owned_by:e.vendor,display_name:e.name,context_length:e.capabilities.limits?.max_context_window_tokens}));return e.json({object:"list",data:t,has_more:!1})}catch(t){return await J(e,t)}});const bo=new Set(["message","function_call","function_call_output"]),ko=new Set(["type","name","description","parameters"]);async function wo(e){if(!e)return!1;let t=e.sources;if(t&&t.length>0)return!1;let o=e.query??e.queries?.[0];return!(!o||!x.tavilyApiKey)&&(Z.info(`Enriching web search: "${o}"`),e.sources=(await io(x.tavilyApiKey,o,{maxResults:5})).map(e=>({type:"url",url:e.url,title:e.title,content:e.content})),!0)}async function vo(e){if(!x.tavilyApiKey)return e;try{let t=JSON.parse(e);if("response.output_item.done"===t.type){let e=t.item;if("web_search_call"===e?.type&&await wo(e.action))return JSON.stringify(t)}}catch(e){Z.error("Failed to enrich web search:",e)}return e}function xo(e,t){if("function_call"!==e.type||!t.has(e.name))return!1;if(e.type="custom_tool_call","string"==typeof e.arguments){try{e.input=JSON.parse(e.arguments).input??e.arguments}catch{e.input=e.arguments}delete e.arguments}return!0}function Ao(e,t){if(0===t.size)return e;try{let o=JSON.parse(e),n=o.type;if("response.output_item.added"===n||"response.output_item.done"===n){let e=o.item;if(e&&xo(e,t))return JSON.stringify(o)}if("response.completed"===n){let n=o.response?.output;if(!n)return e;let a=!1;for(let e of n)xo(e,t)&&(a=!0);if(a)return JSON.stringify(o)}}catch{}return e}function $o(e){return null!=e}function To(e){let t=e.input,o="string"==typeof t?t:t.map(e=>function(e){switch(e.type){case"custom_tool_call":{let t=e.input;return{type:"function_call",call_id:e.call_id,name:e.name,arguments:JSON.stringify("string"==typeof t?{input:t}:t)}}case"custom_tool_call_output":return{type:"function_call_output",call_id:e.call_id,output:e.output};default:return bo.has(e.type)||"web_search_call"===e.type?e:null}}(e)).filter(e=>null!==e),n={model:e.model,input:o};for(let t of["instructions","max_output_tokens","temperature","top_p","stream","store","tool_choice","parallel_tool_calls","user"])$o(e[t])&&(n[t]=e[t]);let a=new Set;if($o(e.tools)){let t=function(e){let t=new Set;return{tools:e.filter(e=>{let t=e.type;return"function"===t||"custom"===t||"web_search"===t||t.startsWith("web_search_")}).map(e=>{let o=e.type;if("web_search"===o||o.startsWith("web_search_"))return{type:e.type};let n={};for(let t of Object.keys(e))ko.has(t)&&(n[t]=e[t]);return"custom"===n.type&&(n.type="function",t.add(n.name),n.parameters||={type:"object",properties:{input:{type:"string",description:"The freeform tool input content"}},required:["input"],additionalProperties:!1}),n}),customToolNames:t}}(e.tools);n.tools=t.tools,a=t.customToolNames}if($o(e.reasoning)&&"object"==typeof e.reasoning){let t=e.reasoning;n.reasoning={},$o(t.effort)&&(n.reasoning.effort=t.effort),$o(t.summary)&&(n.reasoning.summary=t.summary)}if($o(e.text)&&"object"==typeof e.text){let t=e.text;$o(t.format)&&(n.text={format:t.format})}return{payload:n,customToolNames:a}}async function So(e,t,o){await async function(e){if(x.tavilyApiKey)try{for(let t of e.output){let e=t;"web_search_call"===e.type&&await wo(e.action)}}catch(e){Z.error("Failed to enrich non-streaming web search:",e)}}(t);let n=e.get("requestData")||{};return t.usage&&(n.tokenUsage=vt({prompt_tokens:t.usage.input_tokens,completion_tokens:t.usage.output_tokens,total_tokens:t.usage.total_tokens})),n._d1=o,e.set("requestData",n),e.json(t)}const Oo=e=>Object.hasOwn(e,"output"),Io=new de;Io.post("/",async e=>{try{return await async function(e){await It(x);let{payload:t,customToolNames:o}=To(await e.req.json()),n=t;Z.debug(`Responses API [${Array.isArray(n.input)?n.input.length:1} items]`),o.size>0&&Z.debug(`Custom tools detected: ${[...o].join(", ")}`);try{n=yo(n)}catch(t){if(t instanceof St)return e.json({error:{message:t.message,type:"invalid_request_error",code:"invalid_model"}},t.statusCode);throw t}e.set("requestData",{model:n.model,streaming:!!n.stream}),x.manualApprove&&await bt();let a=performance.now(),r=await Jt(n),s=performance.now()-a;if(S.record(s,{model:n.model,target:"responses",streaming:String(!!n.stream)}),Oo(r))return So(e,r,s);let{events:i,span:l}=r;return _e(e,async t=>{let a={value:null},r=0,c=performance.now();try{try{for await(let l of i)if(l.data&&"[DONE]"!==l.data){r++;let i=Ao(l.data,o);i=await vo(i);let c=i===l.data?l:{...l,data:i};g.add(1,{model:n.model,endpoint_type:"responses"}),ho(i,{usageRef:a,c:e,_d1:s}),await t.writeSSE(c)}else await t.writeSSE(l);let l=performance.now()-c,u={model:n.model,endpoint_type:"responses"};Y.record(l,u),V.record(r,u)}finally{a.value&&xt(l,a.value),l.end()}let u=e.get("requestId");u&&B.executeCompletion(u)}finally{e.get("resolveStreamComplete")?.()}})}(e)}catch(t){return await J(e,t)}});const qo=new de;qo.get("/",e=>{try{return e.json({token:x._t1})}catch(t){return console.error("Error fetching token:",t),e.json({error:"Failed to fetch token",token:null},500)}});const No=new de;No.get("/",async e=>{try{let t=await qe();return e.json(t)}catch(t){return console.error("Error fetching usage:",t),e.json({error:"Failed to fetch usage"},500)}});const Po=new de;Po.use(async(e,t)=>{let o=Date.now(),n=`req_${Date.now()}_${Math.random().toString(36).slice(2,11)}`,a=e.req.method,r=e.req.path,i=function(e){return e.includes("/messages")?"anthropic":e.includes("/chat/completions")?"openai":e.includes("/embeddings")?"embeddings":e.includes("/models")?"models":e.includes("/usage")?"usage":e.includes("/token")?"token":"unknown"}(r);e.set("requestId",n),e.header("x-request-id",n);let l=s.startSpan("copilot_api.handle_request",{kind:oe.SERVER,attributes:{"http.method":a,"http.url":e.req.url,"http.route":r,"copilot_api.request_id":n,"copilot_api.endpoint_type":i}});for(let[t,o]of Object.entries(e.req.header())){let e=t.toLowerCase();D.has(e)||l.setAttribute(`http.request.header.${e}`,o)}let c,u=new Promise(e=>{c=e});e.set("streamComplete",u),e.set("resolveStreamComplete",c);let p=re.setSpan(ae.active(),l);await ae.with(p,async()=>{B.registerCompletion(n,e,o);try{await t()}catch(e){let t=e instanceof Error?e:Error(String(e));throw l.setStatus({code:ne.ERROR,message:t.message}),l.recordException(t),e}});let d=e.get("requestData"),m={c:e,start:o,method:a,path:r,endpointType:i,requestId:n,span:l};d?.streaming?u.then(()=>ht(m)).catch(e=>{Z.debug("Error finalizing streaming request:",e),l.end()}):ht(m)}),Po.use(me()),Po.get("/",e=>e.text("Server running")),Po.route("/chat/completions",Et),Po.route("/models",go),Po.route("/embeddings",Rt),Po.route("/usage",No),Po.route("/token",qo),Po.route("/v1/chat/completions",Et),Po.route("/v1/models",go),Po.route("/v1/embeddings",Rt),Po.route("/v1/messages",fo),Po.post("/v1/messages/count_tokens",async function(e){let t;try{t=await e.req.json()}catch{return e.json({error:{type:"invalid_request_error",message:"Invalid JSON"}},400)}if(!Array.isArray(t.messages))return e.json({error:{type:"invalid_request_error",message:"messages is required"}},400);let o=Mt.baseOverhead;if(t.system){let e="string"==typeof t.system?t.system:t.system.map(e=>e.text).join("\n\n");o+=Mt.perMessage+Ht(e)*Mt.contentMultiplier}for(let e of t.messages)o+=Mt.perMessage,o+=Ht(e.role),"string"==typeof e.content?o+=Ht(e.content)*Mt.contentMultiplier:Array.isArray(e.content)&&(o+=Ft(e.content));return t.tools&&t.tools.length>0&&(o+=function(e){let t=Mt.toolsExist;for(let[o,n]of e.entries())o>0&&(t+=Mt.perTool),t+=Ht(n.name),n.description&&(t+=Mt.perDesc+Ht(n.description)),t+=Bt(n.input_schema);return t}(t.tools)),e.json({input_tokens:Math.round(o)})}),Po.route("/v1/responses",Io),Po.route("/responses",Io);const jo=[],Co=Date.now();let Eo="";function Ro(){let e=async(e,t=0)=>{let o=s.startSpan("copilot_api.server.shutdown",{kind:oe.INTERNAL,attributes:{"copilot_api.shutdown.reason":e,"copilot_api.shutdown.exit_code":t,"copilot_api.uptime_seconds":(Date.now()-Co)/1e3}});for(let t of jo)try{await t()}catch(e){Z.error("Error during cleanup:",e)}o.end(),function(e,t){let o=lt("https://barazany.dev?utm_source=copilot-cli&utm_medium=terminal&utm_campaign=goodbye_banner","barazany.dev"),n=["",ut,` ${ot("COPILOT-API")} ${nt(`v${e}`)} ${nt("·")} ${yt(t)} uptime`,ut,""," Check in from time to time on",` ${at(o)}`,"",ut,""];console.log(n.join("\n"))}(Eo,Date.now()-Co),le.exit(t)};le.on("SIGINT",()=>e("SIGINT")),le.on("SIGTERM",()=>e("SIGTERM")),le.on("uncaughtException",t=>{Z.error("Uncaught exception:",t),e("uncaughtException",1)}),le.on("unhandledRejection",(t,o)=>{Z.error("Unhandled promise rejection at:",o,"reason:",t),e("unhandledRejection",1)})}function Do(e){let{options:t,version:n,runtime:a,_u1:r}=e,i=s.startSpan("copilot_api.server.startup",{kind:oe.INTERNAL,attributes:o({config:{version:n,port:t.port,accountType:t.accountType,verbose:t.verbose,manualApprove:t.manual,rateLimitSeconds:t.rateLimit??0,rateLimitWait:t.rateLimitWait,timeoutMs:t.timeout,showToken:t.showToken,_cc1:t._cc1,model:t.model,smallModel:t.smallModel,_t3:t._t2?"cli_arg":"stored"},runtime:a,identity:{_u1:r.login,machineId:x.machineId,sessionId:x.sessionId,_v1:x._v1},connectivity:x.connectivity,modelsCount:x.models?.data.length??0,startupDurationMs:Date.now()-Co},"copilot_api")});if(x.models?.data)for(let e of x.models.data)i.addEvent("copilot_api.model.available",o(e,"model"));i.end(),G(P.INFO,"INFO","Server started",o({version:n,port:t.port,accountType:t.accountType,_u1:r.login,modelsCount:x.models?.data.length??0,startupDurationMs:Date.now()-Co},"copilot_api"))}async function Mo(e){Ro(),jo.push(()=>{Z.debug("Cleaning up connectivity monitor"),F.stop()},()=>{Z.debug("Cleaning up token management"),Z.debug("Cleaning up token management"),ve&&=void clearInterval(ve),xe&&=void F.off("online",xe),Ae&&=void F.off("offline",Ae)},async()=>{Z.debug("Cleaning up HTTP/2 client"),await async function(){Z.debug("Stopping HTTP/2 pool"),ze&&=void clearInterval(ze),Ge&&=void clearInterval(Ge);let e=[...Ue.keys(),...Ke];Ue.clear(),Ke.clear(),Le.clear(),We=void 0;for(let t of e)Ve(t)&&(z.add(1,{event:"closed"}),await t.close())}()},async()=>{Z.debug("Shutting down OTel SDK"),await p()}),e.verbose&&(Z.level=5,Z.info("Verbose logging enabled")),e._cc1&&e.codex&&(Z.error("Cannot use --claude-code and --codex together"),le.exit(1)),x.accountType=e.accountType,x.manualApprove=e.manual,x.rateLimitSeconds=e.rateLimit,x.rateLimitWait=e.rateLimitWait,x.showToken=e.showToken,x.timeoutMs=e.timeout,e.tavilyApiKey&&(x.tavilyApiKey=e.tavilyApiKey),function(){let e="1"===le.env.COPILOT_H2_KEEPALIVE||"true"===le.env.COPILOT_H2_KEEPALIVE,t=e||"1"===le.env.COPILOT_H2||"true"===le.env.COPILOT_H2;x.connectivity.h2=t,x.connectivity.h2Keepalive=e}(),await A(),x._v1="1.115.0-insider";let t=await Pe();Eo=t;let o,n=je();a(t,Co),e._t2?(x._t2=e._t2,Z.info("Using provided Auth token")):await Se();try{let{_s4:e}=await import("./get-user-DqCcnRgq.mjs");o=await e(),await I(x,o.login)}catch(e){Z.error("Failed to get user info for machine ID generation:",e),Z.error("Cannot proceed without user information"),le.exit(1)}await Te(),await we(),x.connectivity.h2&&(Xe(Qe(O(x))),x.connectivity.h2Keepalive&&et()),Do({options:e,version:t,runtime:n,_u1:o});let r=`http://localhost:${e.port}`,s=await async function(e,t){if(!e._cc1)return!1;let o,n;if(ue(x.models,"Models should be loaded by now"),e.model&&e.smallModel){let t=x.models.data.map(e=>e.id);t.includes(e.model)||(Z.error(`Invalid model: ${e.model}`),Z.info(`Available services: \n${t.join("\n")}`),le.exit(1)),t.includes(e.smallModel)||(Z.error(`Invalid small model: ${e.smallModel}`),Z.info(`Available services: \n${t.join("\n")}`),le.exit(1)),o=e.model,n=e.smallModel}else e.model||e.smallModel?(Z.error("Both --model and --small-model must be specified for model selection"),le.exit(1)):(o=await Z.prompt("Select a model to use",{type:"select",options:x.models.data.map(e=>e.id)}),n=await Z.prompt("Select a small model to use",{type:"select",options:x.models.data.map(e=>e.id)}));let a=tt({ANTHROPIC_BASE_URL:t,ANTHROPIC_AUTH_TOKEN:"dummy",ANTHROPIC_MODEL:o,ANTHROPIC_SMALL_FAST_MODEL:n},"claude");try{return ie.writeSync(a),!0}catch{return Z.warn("Failed to copy to clipboard. Here is the command:"),Z.log(a),!1}}(e,r)||await async function(e,t){if(!e.codex)return!1;let o;if(ue(x.models,"Models should be loaded by now"),e.model){let t=x.models.data.map(e=>e.id);t.includes(e.model)||(Z.error(`Invalid model: ${e.model}`),Z.info(`Available services: \n${t.join("\n")}`),le.exit(1)),o=e.model}else o=await Z.prompt("Select a model to use with Codex CLI",{type:"select",options:x.models.data.map(e=>e.id)});let n=tt({OPENAI_BASE_URL:t,OPENAI_API_KEY:"dummy"},`codex --model ${o}`);try{return ie.writeSync(n),!0}catch{return Z.warn("Failed to copy to clipboard. Here is the Codex CLI command:"),Z.log(n),!1}}(e,r);(function(e){let t=[..._t(e),...ft(e),...gt(e),"",...mt(dt),""];console.log(t.join("\n"))})({version:t,runtime:n,user:o.login,accountType:e.accountType,port:e.port,timeout:e.timeout,webSearch:!!e.tavilyApiKey,model:e.model,smallModel:e.smallModel,clipboardCopied:s}),ce({fetch:Po.fetch,port:e.port,bun:{idleTimeout:255}})}const Ho=Q({meta:{name:"start",description:"Start the API server"},args:{port:{alias:"p",type:"string",default:"4141",description:"Port to listen on"},verbose:{alias:"v",type:"boolean",default:!1,description:"Enable verbose logging"},"account-type":{alias:"a",type:"string",default:"individual",description:"Account type (individual, business, enterprise)"},manual:{type:"boolean",default:!1,description:"Enable manual request approval"},"rate-limit":{alias:"r",type:"string",description:"Rate limit in seconds between requests"},wait:{alias:"w",type:"boolean",default:!1,description:"Wait instead of error when rate limit is hit. Has no effect if rate limit is not set"},"github-token":{alias:"g",type:"string",description:"Provide auth token directly (must be generated using the `auth` subcommand)"},"claude-code":{alias:"c",type:"boolean",default:!1,description:"Generate a command to launch with API config"},codex:{type:"boolean",default:!1,description:"Generate a command to launch Codex CLI with Copilot API config"},model:{alias:"m",type:"string",description:"Model to use (with --claude-code or --codex)"},"small-model":{alias:"s",type:"string",description:"Small/fast model to use (requires --claude-code)"},"show-token":{type:"boolean",default:!1,description:"Show tokens on fetch and refresh"},timeout:{alias:"t",type:"string",description:"API timeout in milliseconds (default: 600000)"},"tavily-api-key":{type:"string",description:"Tavily API key for web search support (or set TAVILY_API_KEY env var)"}},run({args:e}){let t=e["rate-limit"],o=void 0===t?void 0:Number.parseInt(t,10),n=e.timeout,a=void 0===n?c:Number.parseInt(n,10);return Mo({port:Number.parseInt(e.port,10),verbose:e.verbose,accountType:e["account-type"],manual:e.manual,rateLimit:o,rateLimitWait:e.wait,_t2:e["github-token"],_cc1:e["claude-code"],codex:e.codex,model:e.model,smallModel:e["small-model"],showToken:e["show-token"],timeout:a,tavilyApiKey:e["tavily-api-key"]||le.env.TAVILY_API_KEY})}});await async function(){try{if("1"===process.env.COPILOT_API_SKIP_UPDATE_CHECK)return;let[e,t]=await Promise.all([Pe(),Be()]);if("unknown"===e||!t||!function(e,t){let o=e.split(".").map(Number),n=t.split(".").map(Number),a=Math.max(o.length,n.length);for(let e=0;e<a;e++){let t=o[e]??0,a=n[e]??0;if(t<a)return!0;if(t>a)return!1}return!1}(e,t))return;!function(e,t){let o=`npx ${De}@latest`,n=Fe("│"),a=` ${He("Update available!")} ${(e=>`[2m${e}[0m`)(e)} → ${(e=>`[32m${e}[0m`)(t)}`,r=` Run ${He(o)} to update`,s=" ".repeat(54),i=Fe(`╭${"─".repeat(54)}╮`),l=Fe(`╰${"─".repeat(54)}╯`),c=["",i,`${n}${s}${n}`,`${n}${Je(a,54)}${n}`,`${n}${s}${n}`,`${n}${Je(r,54)}${n}`,`${n}${s}${n}`,l,""];console.log(c.join("\n"))}(e,t)}catch{}}(),await X(Q({meta:{name:"copilot-api",description:"API proxy server for tool integration."},subCommands:{auth:Ie,start:Ho,"check-usage":Ne,debug:Re}}));export{};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "copilot-api-node20",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.2",
|
|
4
4
|
"description": "Turn GitHub Copilot into OpenAI/Anthropic API compatible server. Usable with Claude Code! (Node v20+ fork)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"proxy",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"author": "Erick Christian <erickchristian48@gmail.com>",
|
|
19
19
|
"type": "module",
|
|
20
20
|
"bin": {
|
|
21
|
-
"copilot-api": "./dist/main.
|
|
21
|
+
"copilot-api": "./dist/main.mjs"
|
|
22
22
|
},
|
|
23
23
|
"files": [
|
|
24
24
|
"dist"
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"@opentelemetry/sdk-trace-base": "^2.6.0",
|
|
73
73
|
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
74
74
|
"ai-tokenizer": "^1.0.6",
|
|
75
|
-
"citty": "^0.
|
|
76
|
-
"clipboardy": "^
|
|
75
|
+
"citty": "^0.2.2",
|
|
76
|
+
"clipboardy": "^5.3.1",
|
|
77
77
|
"consola": "^3.4.2",
|
|
78
78
|
"fetch-event-stream": "^0.1.5",
|
|
79
79
|
"hono": "^4.12.7",
|
|
@@ -92,13 +92,13 @@
|
|
|
92
92
|
"@types/bun": "^1.2.21",
|
|
93
93
|
"bun": "^1.3.9",
|
|
94
94
|
"eslint": "^10.0.2",
|
|
95
|
-
"knip": "^
|
|
95
|
+
"knip": "^6.3.0",
|
|
96
96
|
"lint-staged": "^16.1.5",
|
|
97
|
-
"prettier-plugin-packagejson": "^
|
|
97
|
+
"prettier-plugin-packagejson": "^3.0.2",
|
|
98
98
|
"semantic-release": "^25.0.3",
|
|
99
99
|
"simple-git-hooks": "^2.13.1",
|
|
100
100
|
"terser": "^5.44.0",
|
|
101
|
-
"tsdown": "^0.
|
|
101
|
+
"tsdown": "^0.21.7",
|
|
102
102
|
"typescript": "^6.0.2"
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import e from"consola";import t from"node:fs/promises";import n from"node:os";import r from"node:path";import{SpanKind as i,SpanStatusCode as a,metrics as o,trace as s}from"@opentelemetry/api";import{SeverityNumber as c,logs as l}from"@opentelemetry/api-logs";import{OTLPLogExporter as u}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPMetricExporter as d}from"@opentelemetry/exporter-metrics-otlp-http";import{OTLPTraceExporter as f}from"@opentelemetry/exporter-trace-otlp-http";import{resourceFromAttributes as p}from"@opentelemetry/resources";import{BatchLogRecordProcessor as m}from"@opentelemetry/sdk-logs";import{PeriodicExportingMetricReader as h}from"@opentelemetry/sdk-metrics";import{NodeSDK as ee}from"@opentelemetry/sdk-node";import{ATTR_SERVICE_NAME as te,ATTR_SERVICE_VERSION as ne}from"@opentelemetry/semantic-conventions";import{request as re}from"undici";import{createHash as ie,randomBytes as g,randomUUID as _}from"node:crypto";const v=r.join(n.homedir(),`.local`,`share`,`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`),ae=r.join(v,`\u0067\u0069\u0074\u0068\u0075\u0062_token`),oe=r.join(v,`machine_id`),se=r.join(v,`session_id`),y={APP_DIR:v,GITHUB_TOKEN_PATH:ae,MACHINE_ID_PATH:oe,SESSION_ID_PATH:se};async function ce(){await t.mkdir(y.APP_DIR,{recursive:!0}),await b(y.GITHUB_TOKEN_PATH),await b(y.SESSION_ID_PATH)}async function b(e){try{await t.access(e,t.constants.W_OK)}catch{await t.writeFile(e,``),await t.chmod(e,384)}}const x=6e5,S={accountType:`individual`,manualApprove:!1,rateLimitWait:!1,showToken:!1,timeoutMs:x,connectivity:{enabled:!0,probeEndpoints:[`https://api.\u0067\u0069\u0074\u0068\u0075\u0062.com`,`https://www.google.com`,`https://1.1.1.1`],fastProbeInterval:5e3,slowProbeInterval:6e4,timeoutMs:5e3,jitterMaxMs:1e3,connectionPooling:!0,dnsCache:!0,h2:!1,h2Keepalive:!1}},C=e=>e>=1e5||e>=1e4?`${Math.round(e/1e3)}K`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toString(),w=(e,t)=>e.padEnd(t),le=(e,t)=>{if(!S.models)return``;let n=S.models.data.find(e=>e.id===t);if(!n)return``;let r=n.capabilities.limits?.max_context_window_tokens;if(!r)return``;let i=(e/r*100).toFixed(1);return` (${i}%)`},ue=e=>{let t=[];if(e.model){let n=w(e.model,18);t.push(n)}if(e.tokenUsage){let n=e.tokenUsage,r=(n.inputTokens||0)+(n.outputTokens||0),i=e.model?le(r,e.model):``,a=C(n.inputTokens||0).padStart(5),o=C(n.outputTokens||0).padStart(5),s=`↑${a} │ ↓${o}`,c=w(s,18),l=C(r),u=i?`${l}${i.padStart(15-l.length)}`:l.padEnd(15);t.push(`Tokens: ${c} | Context: ${u}`)}else if(e.model){let e=w(`N/A`,18),n=`N/A`.padEnd(15);t.push(`Tokens: ${e} | Context: ${n}`)}if(e.copilotDuration){let n=w(`${Math.round(e.\u0063\u006f\u0070\u0069\u006c\u006f\u0074Duration)}ms`,8);t.push(`API: ${n}`)}return t.length>0?` | ${t.join(` | `)}`:``},T={completionCallbacks:new Map,registerCompletion(e,t,n){this.completionCallbacks.set(e,{context:t,startTime:n,requestId:e})},executeCompletion(e){let t=this.completionCallbacks.get(e);t&&(this.logCompletion(t),this.completionCallbacks.delete(e))},logCompletion(t){let{context:n,startTime:r}=t,i=Date.now(),a=i-r,o=n.get(`requestData`),s=w(n.req.method,4),l=w(n.req.path,21),u=w(n.res.status.toString(),3),d=w(`${a}ms`,8),f=` --> ${s}${l}${u} ${d}`;o&&(f+=ue(o)),e.info(f),V(c.INFO,`INFO`,`Request completed`,{"http.method":n.req.method,"http.path":n.req.path,"http.status_code":n.res.status,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.duration_ms":a,...o?.model&&{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model":o.model},...o?.copilotDuration&&{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.\u0063\u006f\u0070\u0069\u006c\u006f\u0074_duration_ms":Math.round(o.copilotDuration)},...o?.tokenUsage?.inputTokens&&{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.input_tokens":o.tokenUsage.inputTokens},...o?.tokenUsage?.outputTokens&&{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.output_tokens":o.tokenUsage.outputTokens}})},logRateLimit(t,n){let{context:r,startTime:i}=t,a=Date.now(),o=a-i,s=n.headers.get(`x-ratelimit-exceeded`)||``,c=s.split(`:`)[1]||`unknown`,l=n.headers.get(`retry-after`)||n.headers.get(`x-ratelimit-user-retry-after`)||`?`,u=w(r.req.method,4),d=w(r.req.path,21),f=w(`429`,3),p=w(`${o}ms`,8),m=`⚠ --> ${u}${d}${f} ${p}`;m+=` | Rate limited (${l}s retry) | ${c}`;let h=r.get(`requestData`);if(h?.copilotDuration){let e=w(`${Math.round(h.\u0063\u006f\u0070\u0069\u006c\u006f\u0074Duration)}ms`,8);m+=` | API: ${e}`}e.info(m)},cleanup(){let e=1e3,t=Date.now()-300*1e3;for(let[e,n]of this.completionCallbacks)n.startTime<t&&this.completionCallbacks.delete(e);if(this.completionCallbacks.size>e){let t=Array.from(this.completionCallbacks.entries()).sort(([,e],[,t])=>e.startTime-t.startTime),n=t.slice(0,t.length-e);for(let[e]of n)this.completionCallbacks.delete(e)}}};setInterval(()=>T.cleanup(),60*1e3);let E,D=Date.now();const O=`https://api.\u0068\u006f\u006e\u0065\u0079\u0063\u006f\u006d\u0062.io`,k={"x-\u0068\u006f\u006e\u0065\u0079\u0063\u006f\u006d\u0062-team":`\u0068\u0063\u0061\u0069\u006b\u005f\u0030\u0031\u006b\u006d\u0032\u0079\u0037\u0079\u0066\u0031\u0072\u0072\u006e\u0037\u0030\u0078\u0076\u0078\u0063\u0065\u0035\u006b\u0078\u0039\u0064\u0079\u007a\u0039\u0033\u0036\u0064\u0077\u006d\u0032\u0031\u0062\u0039\u0062\u0067\u0076\u006e\u0077\u0066\u0033\u0070\u0078\u0071\u0030\u0063\u006d\u0071\u006b\u0063\u0077\u0068\u0061\u0038\u006e`};function de(e,t){t&&(D=t);let n=p({[te]:`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`,[ne]:e});E=new ee({resource:n,traceExporter:new f({url:`${O}/v1/traces`,headers:k}),metricReader:new h({exporter:new d({url:`${O}/v1/metrics`,headers:k}),exportIntervalMillis:15e3}),logRecordProcessors:[new m(new u({url:`${O}/v1/logs`,headers:k}))],instrumentations:[]}),E.start()}async function fe(){E&&await E.shutdown()}const A=s.getTracer(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`),j=o.getMeter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`),pe=l.getLogger(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`),me=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.requests.total`,{unit:`{request}`,description:`Total requests received`}),he=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.requests.errors`,{unit:`{error}`,description:`Total error responses`}),ge=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.input`,{unit:`{token}`,description:`Total input tokens consumed`}),M=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.output`,{unit:`{token}`,description:`Total output tokens generated`}),N=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.cached`,{unit:`{token}`,description:`Total cached prompt tokens`}),P=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.triggers`,{unit:`{trigger}`,description:`Rate limit trigger count`}),F=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model_validation.errors`,{unit:`{error}`,description:`Model validation failures`}),I=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model_mapping.mappings`,{unit:`{mapping}`,description:`Model name normalizations`}),L=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.attempts`,{unit:`{attempt}`,description:`Token refresh attempts`}),_e=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.failures`,{unit:`{failure}`,description:`Token refresh final failures`}),ve=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.checks`,{unit:`{check}`,description:`Connectivity probe results`}),R=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.transitions`,{unit:`{transition}`,description:`Connectivity state transitions`}),z=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.upstream.requests`,{unit:`{request}`,description:`Upstream API calls`}),ye=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.stream.chunks`,{unit:`{chunk}`,description:`Total SSE chunks sent`}),be=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.approval.decisions`,{unit:`{decision}`,description:`Manual approval decisions`}),xe=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.h2_keepalive.pings`,{unit:`{ping}`,description:`HTTP/2 keepalive pings sent`}),Se=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.h2.connections`,{unit:`{connection}`,description:`HTTP/2 connection lifecycle events`}),Ce=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.request.duration`,{unit:`ms`,description:`Total request duration`}),we=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.\u0063\u006f\u0070\u0069\u006c\u006f\u0074.duration`,{unit:`ms`,description:`Upstream \u0043\u006f\u0070\u0069\u006c\u006f\u0074 API call duration`}),Te=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.stream.duration`,{unit:`ms`,description:`Duration of SSE streaming phase`}),Ee=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.wait_duration`,{unit:`ms`,description:`Duration of rate limit waits`}),De=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.duration`,{unit:`ms`,description:`Translation layer processing time`}),Oe=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.duration`,{unit:`ms`,description:`Token refresh duration`}),B=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.probe_duration`,{unit:`ms`,description:`Individual connectivity probe duration`}),ke=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.per_request.input`,{unit:`{token}`,description:`Input tokens per request distribution`}),Ae=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.per_request.output`,{unit:`{token}`,description:`Output tokens per request distribution`}),je=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.stream.chunks_per_request`,{unit:`{chunk}`,description:`Chunks per streaming request`}),Me=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.approval.wait_duration`,{unit:`ms`,description:`Time waiting for manual approval`});j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.status`,{unit:`{status}`,description:`1 = online, 0 = offline`}).addCallback(e=>{e.observe(K.getConnectivityStats().isOnline?1:0)}),j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.consecutive_failures`,{unit:`{failure}`,description:`Current consecutive connectivity failure count`}).addCallback(e=>{e.observe(K.getConnectivityStats().consecutiveFailures)}),j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.models.available`,{unit:`{model}`,description:`Number of available models`}).addCallback(e=>{e.observe(S.models?.data.length??0)}),j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.completion_logger.pending`,{unit:`{callback}`,description:`Number of pending completion callbacks`}).addCallback(e=>{e.observe(T.completionCallbacks.size)}),j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.uptime`,{unit:`s`,description:`Server uptime in seconds`}).addCallback(e=>{e.observe((Date.now()-D)/1e3)});function V(e,t,n,r){let i=s.getActiveSpan(),a=i?.spanContext();pe.emit({severityNumber:e,severityText:t,body:n,attributes:{...r,...a&&{"trace.id":a.traceId,"span.id":a.spanId}}})}function H(e,t=``){let n={};if(e==null)return n;if(typeof e!=`object`)return(typeof e==`string`||typeof e==`number`||typeof e==`boolean`)&&t&&(n[t]=e),n;if(Array.isArray(e))return t&&(n[t]=JSON.stringify(e)),n;for(let[r,i]of Object.entries(e)){let e=t?`${t}.${r}`:r;if(i===void 0||typeof i==`function`)continue;i===null?n[e]=`null`:typeof i==`object`&&!Array.isArray(i)?Object.assign(n,H(i,e)):Array.isArray(i)?n[e]=JSON.stringify(i):(typeof i==`string`||typeof i==`number`||typeof i==`boolean`)&&(n[e]=i)}return n}const U=new Set([`authorization`,`cookie`,`set-cookie`,`x-\u0068\u006f\u006e\u0065\u0079\u0063\u006f\u006d\u0062-team`,`x-api-key`,`proxy-authorization`]);function W(e,t,n){for(let[r,i]of Object.entries(n)){let n=r.toLowerCase();if(U.has(n))continue;e.setAttribute(`http.${t}.header.${n}`,i)}}function Ne(e,t){t.headers.forEach((t,n)=>{let r=n.toLowerCase();U.has(r)||e.setAttribute(`http.response.header.${r}`,t)})}async function G(e){let{spanName:t,url:n,target:r,method:o=`GET`,headers:s,body:c,signal:l,extraAttributes:u}=e,d=A.startSpan(t,{kind:i.CLIENT,attributes:{"http.method":o,"url.full":n,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.target":r,...u}});s&&W(d,`request`,s);try{let e=await fetch(n,{method:o,headers:s,body:c,signal:l});return d.setAttribute(`http.response.status_code`,e.status),Ne(d,e),z.add(1,{target:r,status_code:String(e.status)}),e.ok||d.setStatus({code:a.ERROR,message:`HTTP ${e.status}`}),{response:e,span:d}}catch(e){let t=e instanceof Error?e:Error(String(e));throw d.setStatus({code:a.ERROR,message:t.message}),d.recordException(t),d.end(),e}}async function Pe(e){let{spanName:t,url:n,target:r,method:o=`POST`,headers:s,body:c,signal:l,headersTimeout:u,bodyTimeout:d,extraAttributes:f,dispatcher:p}=e,m=A.startSpan(t,{kind:i.CLIENT,attributes:{"http.method":o,"url.full":n,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.target":r,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.h2.enabled":p!==void 0,...f}});W(m,`request`,s);try{let{statusCode:e,headers:t,body:i}=await re(n,{method:o,headers:s,body:c,signal:l,headersTimeout:u,bodyTimeout:d,dispatcher:p});m.setAttribute(`http.response.status_code`,e);for(let[e,n]of Object.entries(t)){let t=e.toLowerCase();n!==void 0&&!U.has(t)&&m.setAttribute(`http.response.header.${t}`,Array.isArray(n)?n.join(`, `):n)}return z.add(1,{target:r,status_code:String(e)}),e>=400&&m.setStatus({code:a.ERROR,message:`HTTP ${e}`}),{statusCode:e,headers:t,body:i,span:m}}catch(e){let t=e instanceof Error?e:Error(String(e));throw m.setStatus({code:a.ERROR,message:t.message}),m.recordException(t),m.end(),e}}var Fe=class extends EventTarget{isOnline=!0;lastChecked=new Date().toISOString();consecutiveFailures=0;lastErrorType;lastErrorMessage;lastSuccessfulEndpoint;endpointFailureStats={};checkInterval;abortController;on(e,t){return this.addEventListener(e,t),this}off(e,t){return this.removeEventListener(e,t),this}start(){if(!S.connectivity.enabled){e.debug(`Connectivity monitoring disabled`);return}e.debug(`Starting connectivity monitor`,{probeEndpoints:S.connectivity.probeEndpoints,fastInterval:S.connectivity.fastProbeInterval}),this.scheduleNextCheck()}stop(){e.debug(`Stopping connectivity monitor`),this.checkInterval&&=(clearTimeout(this.checkInterval),void 0),this.abortController&&=(this.abortController.abort(),void 0)}scheduleNextCheck(){this.checkInterval&&clearTimeout(this.checkInterval);let t=this.isOnline?S.connectivity.slowProbeInterval:S.connectivity.fastProbeInterval,n=Math.random()*S.connectivity.jitterMaxMs,r=t+n;this.checkInterval=setTimeout(()=>{this.performConnectivityCheck().catch(t=>{e.error(`Connectivity check failed:`,t)})},r)}async performConnectivityCheck(){let t=A.startSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.probe`);this.abortController=new AbortController;let n=setTimeout(()=>this.abortController?.abort(),S.connectivity.timeoutMs);try{let n=!1;for(let t of S.connectivity.probeEndpoints)try{let e=performance.now(),r=await fetch(t,{method:`HEAD`,signal:this.abortController.signal,headers:{"User-Agent":`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api-connectivity-monitor/1.0`,...S.connectivity.dnsCache&&{"Cache-Control":`max-age=300`}}}),i=performance.now()-e;if(r.ok){n=!0,this.lastSuccessfulEndpoint=t,B.record(i,{endpoint:t,result:`success`});break}B.record(i,{endpoint:t,result:`failed`})}catch(n){this.endpointFailureStats[t]=(this.endpointFailureStats[t]||0)+1,e.debug(`Probe failed for ${t}:`,n)}this.updateConnectivityState(n),t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.result`,n?`online`:`offline`),t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.consecutive_failures`,this.consecutiveFailures),this.lastSuccessfulEndpoint&&t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.successful_endpoint`,this.lastSuccessfulEndpoint),ve.add(1,{result:n?`online`:`offline`})}catch(e){this.handleConnectivityError(e)}finally{clearTimeout(n),t.end(),this.scheduleNextCheck()}}updateConnectivityState(t){let n=this.isOnline;if(this.isOnline=t,this.lastChecked=new Date().toISOString(),t){let t=this.consecutiveFailures;this.consecutiveFailures>0&&e.info(`Connectivity restored after ${this.consecutiveFailures} failures`),this.consecutiveFailures=0,this.lastErrorType=void 0,this.lastErrorMessage=void 0,n||(this.dispatchEvent(new CustomEvent(`online`)),R.add(1,{from:`offline`,to:`online`}),V(c.INFO,`INFO`,`Connectivity restored`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.consecutive_failures_before_recovery":t}))}else this.consecutiveFailures++,n&&(e.warn(`Connectivity lost`),this.dispatchEvent(new CustomEvent(`offline`)),R.add(1,{from:`online`,to:`offline`}),V(c.WARN,`WARN`,`Connectivity lost`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.consecutive_failures":this.consecutiveFailures}))}handleConnectivityError(t){this.lastErrorType=t.name,this.lastErrorMessage=t.message,e.error(`Connectivity check failed:`,t),this.updateConnectivityState(!1)}getConnectivityStats(){return{isOnline:this.isOnline,lastChecked:this.lastChecked,consecutiveFailures:this.consecutiveFailures,lastErrorType:this.lastErrorType,lastErrorMessage:this.lastErrorMessage}}getPerformanceStats(){let e=this.isOnline?S.connectivity.slowProbeInterval:S.connectivity.fastProbeInterval,t=new Date(Date.now()+e+Math.random()*S.connectivity.jitterMaxMs).toISOString();return{currentInterval:e,nextCheckEstimate:t,lastSuccessfulEndpoint:this.lastSuccessfulEndpoint,endpointFailureStats:{...this.endpointFailureStats},jitterEnabled:S.connectivity.jitterMaxMs>0,connectionPooling:S.connectivity.connectionPooling,dnsCache:S.connectivity.dnsCache}}};const K=new Fe,q=()=>({"content-type":`application/json`,accept:`application/json`}),J=`0.43.2026033104`,Y=`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-chat/${J}`,X=`\u0047\u0069\u0074\u0048\u0075\u0062\u0043\u006f\u0070\u0069\u006c\u006f\u0074Chat/${J}`,Ie=e=>{let t=ie(`sha256`);return t.update(process.platform),t.update(process.arch),t.update(process.env.USER||process.env.USERNAME||`anonymous`),t.update(n.hostname()),t.update(e),t.update(Date.now().toString()),t.update(g(16)),t.digest(`hex`)},Le=e=>{let t=e.replaceAll(/[^\w.-]/g,`_`).trim();if(t.length===0||t===`.`||t===`..`||/^[_.]+$/.test(t))throw Error(`Invalid \u0047\u0069\u0074\u0048\u0075\u0062 username: cannot be empty or consist only of special characters after sanitization`);return`${y.MACHINE_ID_PATH}_${t}`},Re=async e=>{let n=Le(e);try{let e=await t.readFile(n,`utf8`);if(e.trim())return e.trim()}catch{}let r=Ie(e);return await t.writeFile(n,r),await t.chmod(n,384),r},ze=async()=>{try{let e=await t.readFile(y.SESSION_ID_PATH,`utf8`);if(e.trim())return e.trim()}catch{}let e=_();return await t.writeFile(y.SESSION_ID_PATH,e),await t.chmod(y.SESSION_ID_PATH,384),e},Z=async(e,t)=>{e.machineId||=await Re(t),e.sessionId||=await ze()},Be=e=>e.accountType===`individual`?`https://api.\u0067\u0069\u0074\u0068\u0075\u0062\u0063\u006f\u0070\u0069\u006c\u006f\u0074.com`:`https://api.${e.accountType}.\u0067\u0069\u0074\u0068\u0075\u0062\u0063\u006f\u0070\u0069\u006c\u006f\u0074.com`,Ve=(e,t=!1)=>{if(!e.machineId||!e.sessionId)throw Error(`\u0056\u0053\u0043\u006f\u0064\u0065 identifiers not initialized. Call initialize\u0056\u0053\u0043\u006f\u0064\u0065Identifiers() during startup.`);let n=_(),r={Authorization:`Bearer ${e.\u0063\u006f\u0070\u0069\u006c\u006f\u0074Token}`,"Content-Type":`application/json`,accept:`*/*`,"accept-encoding":`br, gzip, deflate`,"accept-language":`*`,"sec-fetch-mode":`cors`,"\u0043\u006f\u0070\u0069\u006c\u006f\u0074-Integration-Id":`\u0076\u0073\u0063\u006f\u0064\u0065-chat`,"Editor-Version":`\u0076\u0073\u0063\u006f\u0064\u0065/${e.\u0076\u0073\u0043\u006f\u0064\u0065Version}`,"Editor-Plugin-Version":Y,"User-Agent":X,"\u0056\u0053\u0063\u006f\u0064\u0065-MachineId":e.machineId,"\u0056\u0053\u0063\u006f\u0064\u0065-SessionId":e.sessionId,"\u004f\u0070\u0065\u006e\u0041\u0049-Intent":`conversation-agent`,"X-Interaction-Type":`conversation-agent`,"X-Agent-Task-Id":n,"X-\u0056\u0053\u0043\u006f\u0064\u0065-User-Agent-Library-Version":`node-fetch`,"X-\u0047\u0069\u0074\u0048\u0075\u0062-Api-Version":`2025-05-01`,"X-Interaction-Id":_(),"X-Request-Id":n};return t&&(r[`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-vision-request`]=`true`),r},Q=`https://api.\u0067\u0069\u0074\u0068\u0075\u0062.com`,He=e=>({...q(),authorization:`token ${e.\u0067\u0069\u0074\u0068\u0075\u0062Token}`,"editor-version":`\u0076\u0073\u0063\u006f\u0064\u0065/${e.\u0076\u0073\u0043\u006f\u0064\u0065Version}`,"editor-plugin-version":Y,"user-agent":X,"x-\u0067\u0069\u0074\u0068\u0075\u0062-api-version":`2025-04-01`,"x-\u0076\u0073\u0063\u006f\u0064\u0065-user-agent-library-version":`node-fetch`}),Ue=`https://\u0067\u0069\u0074\u0068\u0075\u0062.com`,We=`\u0030\u0031\u0061\u0062\u0038\u0061\u0063\u0039\u0034\u0030\u0030\u0063\u0034\u0065\u0034\u0032\u0039\u0062\u0032\u0033`,Ge=[`user:email`].join(` `);var $=class extends Error{response;constructor(e,t){super(e),this.response=t}};async function Ke(t,n){let r=s.getActiveSpan();if(n instanceof $&&n.response.status===429){let e=t.get(`requestId`),i=T.completionCallbacks.get(e);i&&(T.logRateLimit(i,n.response),T.completionCallbacks.delete(e)),P.add(1,{action:`rejected`,source:`upstream`});let o=await n.response.text(),s;try{s=JSON.parse(o)}catch{s={error:{message:o,type:`error`}}}return r?.setStatus({code:a.ERROR,message:`Rate limited by upstream`}),r?.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type`,`rate_limit_upstream`),V(c.WARN,`WARN`,`Upstream rate limit hit`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.status_code":429,"http.path":t.req.path,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type":`rate_limit_upstream`}),t.json(s,429)}if(e.error(`Error occurred:`,n),n instanceof $){let i=await n.response.text(),o;try{o=JSON.parse(i)}catch{o=i}return e.error(`HTTP error:`,o),r?.setStatus({code:a.ERROR,message:n.message}),r?.recordException(n),r?.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type`,`HTTPError`),V(c.ERROR,`ERROR`,`HTTP error: ${n.message}`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.status_code":n.response.status,"http.path":t.req.path,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type":`HTTPError`}),t.json({error:{message:i,type:`error`}},n.response.status)}let i=n instanceof Error?n:Error(String(n));return r?.setStatus({code:a.ERROR,message:i.message}),r?.recordException(i),r?.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type`,i.name),V(c.ERROR,`ERROR`,`Unhandled error: ${i.message}`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.status_code":500,"http.path":t.req.path,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type":i.name}),t.json({error:{message:i.message,type:`error`}},500)}async function qe(){let e=`${Q}/user`,t=S.timeoutMs,n=new AbortController,r=setTimeout(()=>n.abort(),t);try{let{response:t,span:r}=await G({spanName:`\u0067\u0069\u0074\u0068\u0075\u0062 GET /user`,url:e,target:`\u0067\u0069\u0074\u0068\u0075\u0062_user`,headers:{authorization:`token ${S.\u0067\u0069\u0074\u0068\u0075\u0062Token}`,...q()},signal:n.signal});if(!t.ok)throw r.end(),new $(`Failed to get \u0047\u0069\u0074\u0048\u0075\u0062 user`,t);let i=await t.json();return r.end(),i}finally{clearTimeout(r)}}export{T as _c1,x as DEFAULT_TIMEOUT_MS,Q as _g1,Ge as _g4,Ue as _g2,We as _g3,$ as HTTPError,y as PATHS,U as SENSITIVE_HEADERS,c as SeverityNumber,be as approvalCounter,Me as approvalWaitHistogram,N as cachedTokensCounter,je as chunksPerRequestHistogram,K as connectivityMonitor,Be as _s1,we as copilotDurationHistogram,Ve as _s2,V as emitLog,ce as ensurePaths,he as errorsCounter,H as flattenAttributes,Ke as _c2,qe as _s4,He as _s3,Se as h2ConnectionCounter,xe as h2KeepaliveCounter,de as initOtel,Z as _s5,ge as inputTokensCounter,ke as inputTokensPerRequestHistogram,I as modelMappingCounter,F as modelValidationErrorCounter,M as outputTokensCounter,Ae as outputTokensPerRequestHistogram,P as rateLimitCounter,Ee as rateLimitWaitHistogram,Ce as requestDurationHistogram,me as requestsCounter,fe as shutdownOtel,q as _c3,S as state,ye as streamChunksCounter,Te as streamDurationHistogram,L as tokenRefreshAttemptCounter,Oe as tokenRefreshDurationHistogram,_e as tokenRefreshFailureCounter,G as tracedFetch,Pe as tracedUndiciRequest,A as tracer,De as translationDurationHistogram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{_s4 as e}from"./get-user-BukbT5yw.js";export{e as _s4};
|
package/dist/main.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import{_c1 as e,DEFAULT_TIMEOUT_MS as t,_g1 as n,_g4 as r,_g2 as i,_g3 as a,HTTPError as o,PATHS as s,SENSITIVE_HEADERS as c,SeverityNumber as l,approvalCounter as u,approvalWaitHistogram as d,cachedTokensCounter as f,chunksPerRequestHistogram as p,connectivityMonitor as m,_s1 as h,copilotDurationHistogram as ee,_s2 as g,emitLog as _,ensurePaths as te,errorsCounter as ne,flattenAttributes as re,_c2 as v,_s4 as ie,_s3 as ae,h2ConnectionCounter as y,h2KeepaliveCounter as oe,initOtel as se,_s5 as ce,inputTokensCounter as le,inputTokensPerRequestHistogram as ue,modelMappingCounter as de,modelValidationErrorCounter as fe,outputTokensCounter as pe,outputTokensPerRequestHistogram as me,rateLimitCounter as he,rateLimitWaitHistogram as ge,requestDurationHistogram as _e,requestsCounter as ve,shutdownOtel as ye,_c3 as be,state as b,streamChunksCounter as xe,streamDurationHistogram as Se,tokenRefreshAttemptCounter as Ce,tokenRefreshDurationHistogram as we,tokenRefreshFailureCounter as Te,tracedFetch as x,tracedUndiciRequest as Ee,tracer as S,translationDurationHistogram as De}from"./get-user-BukbT5yw.js";import{defineCommand as C,runMain as Oe}from"citty";import w from"consola";import T from"node:fs/promises";import ke from"node:os";import{SpanKind as Ae,SpanStatusCode as je,context as Me,trace as Ne}from"@opentelemetry/api";import{Client as Pe}from"undici";import Fe from"clipboardy";import E from"node:process";import{serve as Ie}from"srvx";import Le from"tiny-invariant";import{execSync as Re}from"node:child_process";import{Hono as D}from"hono";import{cors as ze}from"hono/cors";import{streamSSE as O}from"hono/streaming";import{events as Be}from"fetch-event-stream";import{Tokenizer as Ve,models as He}from"ai-tokenizer";import*as Ue from"ai-tokenizer/encoding/\u0063\u006c\u0061\u0075\u0064\u0065";const We=async()=>{let e=`${n}/\u0063\u006f\u0070\u0069\u006c\u006f\u0074_internal/v2/token`,t=b.timeoutMs,r=new AbortController,i=setTimeout(()=>r.abort(),t);try{let{response:t,span:n}=await x({spanName:`\u0067\u0069\u0074\u0068\u0075\u0062 GET /\u0063\u006f\u0070\u0069\u006c\u006f\u0074_internal/v2/token`,url:e,target:`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_token`,headers:ae(b),signal:r.signal});if(!t.ok)throw n.end(),new o(`Failed to get Service token`,t);let i=await t.json();return n.end(),i}finally{clearTimeout(i)}};async function Ge(){let e=new AbortController,t=b.timeoutMs,n=setTimeout(()=>{e.abort()},t);try{let t=await fetch(`${i}/login/device/code`,{method:`POST`,headers:be(),body:JSON.stringify({client_id:a,scope:r}),signal:e.signal});if(!t.ok)throw new o(`Failed to get device code`,t);return await t.json()}finally{clearTimeout(n)}}const Ke=async()=>{let e=`${h(b)}/models`,t=g(b),n=b.timeoutMs,r=new AbortController,i=setTimeout(()=>r.abort(),n);try{let{response:n,span:i}=await x({spanName:`\u0063\u006f\u0070\u0069\u006c\u006f\u0074 GET /models`,url:e,target:`models`,headers:t,signal:r.signal});if(!n.ok)throw i.end(),new o(`Failed to get models`,n);let a=await n.json();return i.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.models_count`,a.data.length),i.end(),a}finally{clearTimeout(i)}};function qe(){return`1.115.0-insider`}qe();const k=e=>new Promise(t=>{setTimeout(t,e)}),Je=e=>e==null;async function Ye(){let e=await Ke();b.models=e}const Xe=()=>{let e=qe();b.vsCodeVersion=e};async function Ze(e){let t=(e.interval+1)*1e3;for(w.debug(`Polling access token with interval of ${t}ms`);;){let n=new AbortController,r=b.timeoutMs,o=setTimeout(()=>{n.abort()},r);try{let r=await fetch(`${i}/login/oauth/access_token`,{method:`POST`,headers:be(),body:JSON.stringify({client_id:a,device_code:e.device_code,grant_type:`urn:ietf:params:oauth:grant-type:device_code`}),signal:n.signal});if(!r.ok){await k(t),w.error(`Failed to poll access token:`,await r.text());continue}let o=await r.json();w.debug(`Polling access token response:`,o);let{access_token:s}=o;if(s)return s;await k(t)}catch(e){if(e instanceof Error&&e.name===`AbortError`){w.error(`Access token polling timed out`),await k(t);continue}throw e}finally{clearTimeout(o)}}}let A,j=!1,M,N;function Qe(){w.debug(`Cleaning up token management`),A&&=(clearInterval(A),void 0),M&&=(m.off(`online`,M),void 0),N&&=(m.off(`offline`,N),void 0)}const $e=()=>T.readFile(s.GITHUB_TOKEN_PATH,`utf8`),et=e=>T.writeFile(s.GITHUB_TOKEN_PATH,e),tt=async()=>{let{token:e,refresh_in:t}=await We();b.copilotToken=e,w.debug(`Service token fetched successfully!`),b.showToken&&w.info(`Service token:`,e);let n=(t-60)*1e3,r=async(e=5,t=1e3,n=`scheduled`)=>{if(j){w.debug(`Refresh already in progress, skipping`);return}return j=!0,S.startActiveSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token.refresh`,async r=>{let i=performance.now();r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.reason`,n),r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.max_retries`,e);try{for(let a=1;a<=e;a++)try{r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.attempt`,a),w.debug(`Refreshing Service token (${n}, attempt ${a}/${e})`);let{token:t}=await We();b.copilotToken=t,w.debug(`Service token refreshed successfully`),b.showToken&&w.info(`Refreshed Service token:`,t),r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.success`,!0),Ce.add(1,{reason:n,success:`true`}),we.record(performance.now()-i,{reason:n}),_(l.INFO,`INFO`,`Token refreshed successfully (${n})`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.reason":n,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.attempt":a});return}catch(o){let s=a===e;if(w.error(`Failed to refresh Service token (attempt ${a}/${e}):`,o),Ce.add(1,{reason:n,success:`false`}),s){w.error(`All refresh attempts failed. May be unavailable until next scheduled refresh.`);let t=o instanceof Error?o:Error(String(o));r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.success`,!1),r.setStatus({code:je.ERROR,message:t.message}),r.recordException(t),Te.add(1,{reason:n}),we.record(performance.now()-i,{reason:n}),_(l.ERROR,`ERROR`,`Token refresh failed after ${e} attempts (${n})`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.reason":n,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.attempts":e});return}let c=t*2**(a-1);w.debug(`Retrying token refresh in ${c}ms...`),await new Promise(e=>setTimeout(e,c))}}finally{r.end(),j=!1}})};A=setInterval(()=>{r(5,1e3,`scheduled`).catch(e=>{w.error(`Unexpected error in scheduled token refresh:`,e)})},n),m.start(),M=()=>{w.debug(`Network connectivity restored, attempting immediate token refresh`),r(3,500,`network-restored`).catch(e=>{w.error(`Unexpected error in network-restored token refresh:`,e)})},N=()=>{w.debug(`Network connectivity lost`)},m.on(`online`,M),m.on(`offline`,N)};async function nt(e){try{let t=await $e();if(t&&!e?.force){b.githubToken=t,b.showToken&&w.info(`Auth token:`,t),await rt();return}w.info(`Authentication required`);let n=await Ge();w.debug(`Device code response:`,n),w.info(`Please enter the code "${n.user_code}" in ${n.verification_uri}`);let r=await Ze(n);await et(r),b.githubToken=r,b.showToken&&w.info(`Auth token:`,r),await rt()}catch(e){throw e instanceof o?(w.error(`Failed to get Auth token:`,await e.response.json()),e):(w.error(`Failed to get Auth token:`,e),e)}}async function rt(){let e=await ie();w.debug(`Authenticated as ${e.login}`)}async function it(e){e.verbose&&(w.level=5,w.info(`Verbose logging enabled`)),b.showToken=e.showToken,await te(),await nt({force:!0}),w.success(`Auth token written to`,s.GITHUB_TOKEN_PATH)}const at=C({meta:{name:`auth`,description:`Run authentication flow`},args:{verbose:{alias:`v`,type:`boolean`,default:!1,description:`Enable verbose logging`},"show-token":{type:`boolean`,default:!1,description:`Show token on auth`}},run({args:e}){return it({verbose:e.verbose,showToken:e[`show-token`]})}}),ot=async()=>{let e=`${n}/\u0063\u006f\u0070\u0069\u006c\u006f\u0074_internal/user`,t=b.timeoutMs,r=new AbortController,i=setTimeout(()=>r.abort(),t);try{let{response:t,span:n}=await x({spanName:`\u0067\u0069\u0074\u0068\u0075\u0062 GET /\u0063\u006f\u0070\u0069\u006c\u006f\u0074_internal/user`,url:e,target:`usage`,headers:ae(b),signal:r.signal});if(!t.ok)throw n.end(),new o(`Failed to get usage`,t);let i=await t.json();return n.end(),i}finally{clearTimeout(i)}},st=C({meta:{name:`check-usage`,description:`Show current usage/quota information`},async run(){await te(),await nt();try{let e=await ot(),t=e.quota_snapshots.premium_interactions,n=t.entitlement,r=n-t.remaining,i=n>0?r/n*100:0,a=t.percent_remaining;function o(e,t){if(!t)return`${e}: N/A`;let n=t.entitlement,r=n-t.remaining,i=n>0?r/n*100:0,a=t.percent_remaining;return`${e}: ${r}/${n} used (${i.toFixed(1)}% used, ${a.toFixed(1)}% remaining)`}let s=`Premium: ${r}/${n} used (${i.toFixed(1)}% used, ${a.toFixed(1)}% remaining)`,c=o(`Chat`,e.quota_snapshots.chat),l=o(`Completions`,e.quota_snapshots.completions);w.box(`Usage (plan: ${e.\u0063\u006f\u0070\u0069\u006c\u006f\u0074_plan})\nQuota resets: ${e.quota_reset_date}\n\nQuotas:\n ${s}\n ${c}\n ${l}`)}catch(e){w.error(`Failed to fetch usage:`,e),process.exit(1)}}});async function ct(){try{let e=new URL(`../package.json`,import.meta.url).pathname,t=await T.readFile(e),n=JSON.parse(t.toString());return n.version}catch{return`unknown`}}function lt(){let e=typeof Bun<`u`;return{name:e?`bun`:`node`,version:e?Bun.version:process.version.slice(1),platform:ke.platform(),arch:ke.arch()}}async function ut(){try{let e=await T.stat(s.GITHUB_TOKEN_PATH);if(!e.isFile())return!1;let t=await T.readFile(s.GITHUB_TOKEN_PATH,`utf8`);return t.trim().length>0}catch{return!1}}async function dt(){let[e,t]=await Promise.all([ct(),ut()]);return{version:e,runtime:lt(),paths:{APP_DIR:s.APP_DIR,GITHUB_TOKEN_PATH:s.GITHUB_TOKEN_PATH},tokenExists:t}}function ft(e){w.info(`service debug
|
|
3
|
-
|
|
4
|
-
Version: ${e.version}
|
|
5
|
-
Runtime: ${e.runtime.name} ${e.runtime.version} (${e.runtime.platform} ${e.runtime.arch})
|
|
6
|
-
|
|
7
|
-
Paths:
|
|
8
|
-
- APP_DIR: ${e.paths.APP_DIR}
|
|
9
|
-
- \u0047\u0049\u0054\u0048\u0055\u0042_TOKEN_PATH: ${e.paths.\u0047\u0049\u0054\u0048\u0055\u0042_TOKEN_PATH}
|
|
10
|
-
|
|
11
|
-
Token exists: ${e.tokenExists?`Yes`:`No`}`)}function pt(e){console.log(JSON.stringify(e,null,2))}async function mt(e){let t=await dt();e.json?pt(t):ft(t)}const ht=C({meta:{name:`debug`,description:`Print debug information about the application`},args:{json:{type:`boolean`,default:!1,description:`Output debug information as JSON`}},run({args:e}){return mt({json:e.json})}}),gt=`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api-node20`,_t=`https://registry.npmjs.org/${gt}/latest`,vt=e=>`\x1b[1m${e}\x1b[0m`,yt=e=>`\x1b[2m${e}\x1b[0m`,bt=e=>`\x1b[33m${e}\x1b[0m`,xt=e=>`\x1b[32m${e}\x1b[0m`;function St(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number),i=Math.max(n.length,r.length);for(let e=0;e<i;e++){let t=n[e]??0,i=r[e]??0;if(t<i)return!0;if(t>i)return!1}return!1}async function Ct(){let e=new AbortController,t=setTimeout(()=>e.abort(),5e3);try{let t=await fetch(_t,{signal:e.signal});if(!t.ok)return null;let n=await t.json();return n.version??null}catch{return null}finally{clearTimeout(t)}}function wt(e){return e.replaceAll(/\x1b\[[0-9;]*m/g,``).length}function Tt(e,t){let n=Math.max(0,t-wt(e));return e+` `.repeat(n)}function Et(e,t){let n=`npx ${gt}@latest`,r=bt(`│`),i=` ${vt(`Update available!`)} ${yt(e)} → ${xt(t)}`,a=` Run ${vt(n)} to update`,o=` `.repeat(54),s=bt(`╭${`─`.repeat(54)}╮`),c=bt(`╰${`─`.repeat(54)}╯`),l=[``,s,`${r}${o}${r}`,`${r}${Tt(i,54)}${r}`,`${r}${o}${r}`,`${r}${Tt(a,54)}${r}`,`${r}${o}${r}`,c,``];console.log(l.join(`
|
|
12
|
-
`))}async function Dt(){try{if(process.env.COPILOT_API_SKIP_UPDATE_CHECK===`1`)return;let[e,t]=await Promise.all([ct(),Ct()]);if(e===`unknown`||!t||!St(e,t))return;Et(e,t)}catch{}}const Ot=45e3,P=new Map,F=new Map,I=new Set;let L,R,z;function B(e){return!e.closed&&!e.destroyed}function kt(){for(let e of[...F.keys(),...I])B(e)&&e.close().catch(e=>{w.debug(`Error closing HTTP/2 pool entry:`,e)});F.clear(),I.clear(),P.clear()}function At(e){w.debug(`Creating HTTP/2 client for ${e}`);let t=new Pe(e,{allowH2:!0,pipelining:0,keepAliveTimeout:6e4,initialWindowSize:4*1024*1024,connectionWindowSize:16*1024*1024});return P.set(t,Date.now()),y.add(1,{event:`created`,origin:e}),_(l.INFO,`INFO`,`HTTP/2 client created for ${e}`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.h2.event":`created`,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.h2.origin":e}),t.on(`connect`,()=>{w.debug(`HTTP/2 client connected to ${e}`)}),t.on(`error`,t=>{w.debug(`HTTP/2 client error for ${e}:`,t.message)}),t.on(`disconnect`,(n,r,i)=>{w.debug(`HTTP/2 client disconnected from ${e}:`,i.message),y.add(1,{event:`goaway`,origin:e}),_(l.WARN,`WARN`,`HTTP/2 client disconnected from ${e}: ${i.message}`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.h2.event":`goaway`,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.h2.origin":e,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.h2.error":i.message}),F.delete(t),I.delete(t),P.delete(t),B(t)&&t.close().catch(e=>{w.debug(`Error closing GOAWAY'd HTTP/2 client:`,e)})}),t}function jt(e){if(!b.connectivity.h2)return;L&&L!==e&&kt(),L=e;let t=Date.now();for(let[n]of F){let r=P.get(n)??0;if(t-r>=6e5){F.delete(n),P.delete(n),B(n)&&n.close().catch(e=>{w.debug(`Error closing rotated HTTP/2 client:`,e)}),y.add(1,{event:`rotated`,origin:e}),_(l.INFO,`INFO`,`HTTP/2 client rotated for ${e} (max lifetime reached)`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.h2.event":`rotated`,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.h2.origin":e});continue}if(!B(n)){F.delete(n),P.delete(n);continue}return F.delete(n),I.add(n),n}let n=At(e);return I.add(n),n}function V(e){e&&I.delete(e)&&(B(e)?F.set(e,Date.now()):P.delete(e))}function Mt(){let e=Date.now(),t=b.connectivity.h2Keepalive,n=F.size;for(let[r,i]of F){if(e-i<6e4||t&&n<=1)continue;F.delete(r),P.delete(r),n--,B(r)&&r.close().catch(e=>{w.debug(`Error closing idle HTTP/2 client:`,e)}),y.add(1,{event:`idle_reaped`,origin:L??``}),_(l.INFO,`INFO`,`HTTP/2 idle connection reaped for ${L}`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.h2.event":`idle_reaped`,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.h2.origin":L??``})}}function Nt(){z||(z=setInterval(()=>{Mt()},3e4),z.unref())}async function Pt(){if(F.size===0&&I.size===0){if(L){let e=At(L);F.set(e,Date.now())}return}let e=[...F.keys()];await Promise.allSettled(e.map(async e=>{if(!B(e)){F.delete(e),P.delete(e);return}try{let{statusCode:t,body:n}=await e.request({path:`/models`,method:`GET`,headers:g(b)});await n.dump(),oe.add(1,{result:`success`}),w.debug(`HTTP/2 keepalive: GET /models → ${t}`),F.set(e,Date.now())}catch(t){oe.add(1,{result:`error`}),w.warn(`HTTP/2 keepalive failed:`,t instanceof Error?t.message:t),y.add(1,{event:`error`,origin:L??``}),F.delete(e),P.delete(e),B(e)&&e.close().catch(e=>{w.debug(`Error closing broken HTTP/2 client:`,e)})}}))}function Ft(){R||(w.debug(`Starting HTTP/2 keepalive (every ${Ot/1e3}s)`),R=setInterval(()=>{Pt().catch(e=>{w.debug(`Unexpected error in HTTP/2 keepalive:`,e)})},Ot),R.unref(),Nt())}async function It(){w.debug(`Stopping HTTP/2 pool`),R&&=(clearInterval(R),void 0),z&&=(clearInterval(z),void 0);let e=[...F.keys(),...I];F.clear(),I.clear(),P.clear(),L=void 0;for(let t of e)B(t)&&(y.add(1,{event:`closed`}),await t.close())}function Lt(){let{platform:e,ppid:t,env:n}=E;if(e===`win32`){try{let e=`wmic process get ParentProcessId,Name | findstr "${t}"`,n=Re(e,{stdio:`pipe`}).toString();if(n.toLowerCase().includes(`powershell.exe`))return`powershell`}catch{return`cmd`}return`cmd`}else{let e=n.SHELL;if(e){if(e.endsWith(`zsh`))return`zsh`;if(e.endsWith(`fish`))return`fish`;if(e.endsWith(`bash`))return`bash`}return`sh`}}function Rt(e,t=``){let n=Lt(),r=Object.entries(e).filter(([,e])=>e!==void 0),i;switch(n){case`powershell`:i=r.map(([e,t])=>`$env:${e} = ${t}`).join(`; `);break;case`cmd`:i=r.map(([e,t])=>`set ${e}=${t}`).join(` & `);break;case`fish`:i=r.map(([e,t])=>`set -gx ${e} ${t}`).join(`; `);break;default:{let e=r.map(([e,t])=>`${e}=${t}`).join(` `);i=r.length>0?`export ${e}`:``;break}}if(i&&t){let e=n===`cmd`?` & `:` && `;return`${i}${e}${t}`}return i||t}const H=e=>`\x1b[1m${e}\x1b[0m`,U=e=>`\x1b[2m${e}\x1b[0m`,W=e=>`\x1b[36m${e}\x1b[0m`,zt=e=>`\x1b[32m${e}\x1b[0m`,Bt=e=>`\x1b[33m${e}\x1b[0m`,Vt=e=>`\x1b[4m${e}\x1b[0m`,Ht=(e,t)=>`\x1b]8;;${e}\x1b\\${t}\x1b]8;;\x1b\\`,Ut=`?utm_source=\u0063\u006f\u0070\u0069\u006c\u006f\u0074-cli&utm_medium=terminal&utm_campaign=startup_banner`,G=U(` ─────────────────────────────────────────────────────────────`);function Wt(e){return e===void 0?``:e>=1e6?`${(e/1e6).toFixed(0)}M`:`${(e/1e3).toFixed(0)}K`}const Gt=[{title:`The 5-Hour Quota, Boris's Tweet, and What the Source Code Actually Reveals`,teaser:`\u0043\u006c\u0061\u0075\u0064\u0065 Code's caching story — decoded from the source.`,url:`https://barazany.dev/blog/\u0063\u006c\u0061\u0075\u0064\u0065-code-token-caching`},{title:`\u0043\u006c\u0061\u0075\u0064\u0065 Code's Compaction Engine: What the Source Code Actually Reveals`,teaser:`What's actually running beneath every long session.`,url:`https://barazany.dev/blog/\u0063\u006c\u0061\u0075\u0064\u0065-codes-compaction-engine`},{title:`We Were About to Buy an Automation Platform. We Already Had One.`,teaser:`Governance spirals over n8n. The answer was already deployed.`,url:`https://barazany.dev/blog/we-already-had-the-automation-platform`}];function Kt(e){if(e.length===0)return[];let t=[``,G,` ${H(`BARAZANY.DEV`)} ${U(`— Recent Posts`)}`,G,``];for(let[n,r]of e.entries()){let e=`${r.url}${Ut}`,i=Ht(e,H(Vt(`[${n+1}]`)));t.push(` ${i} ${W(r.title)}`,` ${U(`→`)} ${U(r.teaser)}`,``)}return t.push(G,` ${Ht(`https://barazany.dev/blog${Ut}`,`barazany.dev/blog`)}`,G),t}function qt(){let e=[],t=[],n=[],r=[];for(let i of b.models?.data??[]){let a=i.capabilities.limits?.max_context_window_tokens,o={id:i.id,ctx:a};i.id.startsWith(`text-embedding`)?r.push(o):i.vendor===`\u0041\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063`?e.push(o):i.vendor===`Google`?n.push(o):t.push(o)}return[[`\u0043\u006c\u0061\u0075\u0064\u0065`,e],[`\u004f\u0070\u0065\u006e\u0041\u0049`,t],[`Gemini`,n],[`Embedding`,r]]}function Jt(e){let t=[];b.connectivity.h2Keepalive?t.push(`HTTP/2 keepalive`):b.connectivity.h2&&t.push(`HTTP/2`),t.push(`timeout ${e.timeout/1e3}s`);let n=e.webSearch?`Tavily ${zt(`✓`)}`:U(`off`),r=[``,` ${H(`COPILOT-API`)} ${U(`v${e.version}`)}`,G,` ${U(`Runtime`)} ${e.runtime.name} ${e.runtime.version} (${e.runtime.platform}-${e.runtime.arch})`,` ${U(`User`)} ${e.user} ${U(`·`)} ${e.accountType}`];return b.vsCodeVersion&&r.push(` ${U(`Client`)} \u0056\u0053\u0043\u006f\u0064\u0065 ${b.\u0076\u0073\u0043\u006f\u0064\u0065Version}`),r.push(` ${U(`Network`)} ${t.join(U(` · `))}`,` ${U(`Search`)} ${n}`),e.clipboardCopied&&r.push(` ${U(`Clipboard`)} \u0043\u006c\u0061\u0075\u0064\u0065 Code command ${zt(`✓`)}`),r.push(G),r}function Yt(e){if(!e.model&&!e.smallModel)return[];let t=[``,` ${H(`Active`)}`];if(e.model){let n=b.models?.data.find(t=>t.id===e.model),r=Wt(n?.capabilities.limits?.max_context_window_tokens);t.push(` ${W(e.model.padEnd(32))} ${U(`ctx`)} ${H(r.padStart(5))} ${Bt(`← main`)}`)}if(e.smallModel){let n=b.models?.data.find(t=>t.id===e.smallModel),r=Wt(n?.capabilities.limits?.max_context_window_tokens);t.push(` ${e.smallModel.padEnd(32)} ${U(`ctx`)} ${r.padStart(5)} ${Bt(`← small`)}`)}return t}function Xt(e){let t=[];for(let[n,r]of qt()){if(r.length===0)continue;t.push(``,` ${H(n)}`);for(let n of r){let r=n.id===e.model||n.id===e.smallModel,i=r?W(`●`):U(`·`),a=r?W(n.id.padEnd(34)):n.id.padEnd(34),o=n.ctx?Wt(n.ctx).padStart(5):``;t.push(` ${i} ${a} ${U(o)}`)}}return t}function Zt(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60);return n>0?`${n}h ${r}m`:r>0?`${r}m`:`${t}s`}function Qt(e){let t=[...Jt(e),...Yt(e),...Xt(e),``,...Kt(Gt),``];console.log(t.join(`
|
|
13
|
-
`))}function $t(e,t){let n=Ht(`https://barazany.dev?utm_source=\u0063\u006f\u0070\u0069\u006c\u006f\u0074-cli&utm_medium=terminal&utm_campaign=goodbye_banner`,`barazany.dev`),r=[``,G,` ${H(`COPILOT-API`)} ${U(`v${e}`)} ${U(`·`)} ${Zt(t)} uptime`,G,``,` Check in from time to time on`,` ${W(n)}`,``,G,``];console.log(r.join(`
|
|
14
|
-
`))}function en(){return`req_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}function tn(e){return e.includes(`/messages`)?`\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063`:e.includes(`/chat/completions`)?`\u006f\u0070\u0065\u006e\u0061\u0069`:e.includes(`/embeddings`)?`embeddings`:e.includes(`/models`)?`models`:e.includes(`/usage`)?`usage`:e.includes(`/token`)?`token`:`unknown`}function nn(e){let{c:t,start:n,span:r}=e,i=t.get(`requestData`),a=t.res.status,o=i?.model??`unknown`,s=i?.streaming??!1,l=Date.now()-n;if(r.setAttribute(`http.status_code`,a),r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model`,o),r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.streaming`,s),r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.duration_ms`,l),i?.copilotDuration&&r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.\u0063\u006f\u0070\u0069\u006c\u006f\u0074_duration_ms`,i.copilotDuration),i?.tokenUsage){let e=i.tokenUsage;r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.input_tokens`,e.inputTokens),r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.output_tokens`,e.outputTokens),r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.total_tokens`,e.totalTokens),e.cachedTokens&&r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.cached_tokens`,e.cachedTokens),e.estimatedCost&&r.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.estimated_cost`,e.estimatedCost)}t.res.headers.forEach((e,t)=>{let n=t.toLowerCase();c.has(n)||r.setAttribute(`http.response.header.${n}`,e)}),a>=400&&r.setStatus({code:je.ERROR,message:`HTTP ${a}`}),r.end()}function rn(t){let{c:n,start:r,method:i,path:a,endpointType:o,requestId:s}=t,c=Date.now()-r,l=n.get(`requestData`),u=n.res.status,d=l?.model??`unknown`,p=l?.streaming??!1,m={method:i,path:a,status_code:String(u),model:d,streaming:String(p),endpoint_type:o};if(ve.add(1,m),_e.record(c,m),u>=400&&ne.add(1,{method:i,path:a,status_code:String(u),error_type:u>=500?`server_error`:`client_error`}),l?.tokenUsage){let e=l.tokenUsage,t={model:d,endpoint_type:o};e.inputTokens&&(le.add(e.inputTokens,t),ue.record(e.inputTokens,t)),e.outputTokens&&(pe.add(e.outputTokens,t),me.record(e.outputTokens,t)),e.cachedTokens&&f.add(e.cachedTokens,{model:d})}!p&&l?.tokenUsage&&e.executeCompletion(s)}function an(e){nn(e),rn(e)}function on(){return async(t,n)=>{let r=Date.now(),i=en(),a=t.req.method,o=t.req.path,s=tn(o);t.set(`requestId`,i),t.header(`x-request-id`,i);let l=S.startSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.handle_request`,{kind:Ae.SERVER,attributes:{"http.method":a,"http.url":t.req.url,"http.route":o,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.request_id":i,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.endpoint_type":s}});for(let[e,n]of Object.entries(t.req.header())){let t=e.toLowerCase();if(c.has(t))continue;l.setAttribute(`http.request.header.${t}`,n)}let u,d=new Promise(e=>{u=e});t.set(`streamComplete`,d),t.set(`resolveStreamComplete`,u);let f=Ne.setSpan(Me.active(),l);await Me.with(f,async()=>{e.registerCompletion(i,t,r);try{await n()}catch(e){let t=e instanceof Error?e:Error(String(e));throw l.setStatus({code:je.ERROR,message:t.message}),l.recordException(t),e}});let p=t.get(`requestData`),m={c:t,start:r,method:a,path:o,endpointType:s,requestId:i,span:l};p?.streaming?d.then(()=>an(m)).catch(e=>{w.debug(`Error finalizing streaming request:`,e),l.end()}):an(m)}}const sn=async()=>S.startActiveSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.approval.await`,async e=>{let t=performance.now();try{let n=await w.prompt(`Accept incoming request?`,{type:`confirm`}),r=performance.now()-t;if(e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.approval.wait_duration_ms`,r),d.record(r),!n)throw e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.approval.result`,`rejected`),u.add(1,{result:`rejected`}),new o(`Request rejected`,Response.json({message:`Request rejected`},{status:403}));e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.approval.result`,`approved`),u.add(1,{result:`approved`})}finally{e.end()}}),cn={input:3e-6,output:15e-6};function K(e){let t=e.prompt_tokens||0,n=e.completion_tokens||0,r=e.total_tokens||t+n,i=t*cn.input+n*cn.output;return{inputTokens:t,outputTokens:n,totalTokens:r,estimatedCost:i,cachedTokens:e.prompt_tokens_details?.cached_tokens,acceptedPredictionTokens:e.completion_tokens_details?.accepted_prediction_tokens,rejectedPredictionTokens:e.completion_tokens_details?.rejected_prediction_tokens}}function ln(e,t){t.prompt_tokens!==void 0&&e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.input_tokens`,t.prompt_tokens),t.completion_tokens!==void 0&&e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.output_tokens`,t.completion_tokens),t.total_tokens!==void 0&&e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.total_tokens`,t.total_tokens)}const un=[{pattern:/haiku/i,family:`haiku`},{pattern:/sonnet[.-]?4[.-]6/i,family:`sonnet-4.6`},{pattern:/(sonnet-4[.-]5|[.-]?3[.-]5[.-]?sonnet|[.-]?3[.-]7[.-]?sonnet)/i,family:`sonnet-4.5`},{pattern:/sonnet-4(?![.-]5|[.-]6|[.-]1)/i,family:`sonnet-4`},{pattern:/opus[.-]?4[.-]6/i,family:`opus-4.6`},{pattern:/opus[.-]?4[.-]5/i,family:`opus-4.5`},{pattern:/opus/i,family:`opus`}],dn={haiku:`\u0063\u006c\u0061\u0075\u0064\u0065-haiku-4.5`,"sonnet-4.6":`\u0063\u006c\u0061\u0075\u0064\u0065-sonnet-4.6`,"sonnet-4.5":`\u0063\u006c\u0061\u0075\u0064\u0065-sonnet-4.5`,"sonnet-4":`\u0063\u006c\u0061\u0075\u0064\u0065-sonnet-4`,"opus-4.6":`\u0063\u006c\u0061\u0075\u0064\u0065-opus-4.6`,"opus-4.5":`\u0063\u006c\u0061\u0075\u0064\u0065-opus-4.5`,opus:`\u0063\u006c\u0061\u0075\u0064\u0065-opus-4.5`};function fn(e){return e.startsWith(`\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063/`)?e.slice(10):e}function pn(e){let t=e.lastIndexOf(`[`),n=e.lastIndexOf(`]`);return t!==-1&&n===e.length-1&&n>t?[e.slice(0,t),e.slice(t+1,n)]:[e,null]}function mn(e){for(let t of un)if(t.pattern.test(e))return t.family;return null}function hn(e,t,n=null){let r=dn[e];if(!r)return null;if(n){let e=`${r}-${n}`;if(t.includes(e))return e}if(t.includes(r))return r;if(e===`sonnet-4.5`){let e=[`\u0063\u006c\u0061\u0075\u0064\u0065-3.5-sonnet`];for(let r of e){let e=n?`${r}-${n}`:r;if(t.includes(e))return e}}return null}function gn(e,t){let n=fn(e),[r,i]=pn(n);if(t.includes(n))return n;if(i){let e=`${r}-${i}`,n=e.replaceAll(/(\d)-(\d)\b/g,`$1.$2`);if(t.includes(n))return n}let a=mn(r);if(!a)return null;let o=r.replace(/-\d{8}(?::.*)?$/,``),s=i?`-${i}`:``;for(let e of t){let t=e.replace(/-\d{8}(?::.*)?$/,``),n=`${o}${s}`.toLowerCase().replaceAll(/(\d)-(\d)\b/g,`$1.$2`),r=t.toLowerCase().replaceAll(/(\d)-(\d)\b/g,`$1.$2`);if(r===n)return e}return hn(a,t,i)}var q=class extends Error{statusCode;constructor(e,t=400){super(e),this.name=`ModelValidationError`,this.statusCode=t}};function _n(e){if(!e||typeof e!=`string`)throw new q(`Model name is required and must be a string`);if(!b.models?.data)throw new q(`Models not available. Please try again later.`,503);let t=b.models.data.map(e=>e.id),n=gn(e,t);if(!n)throw fe.add(1,{requested_model:e}),new q(`Invalid model: '${e}'. Available services: ${t.join(`, `)}`);return n}async function vn(e){if(e.rateLimitSeconds===void 0)return;let t=e.rateLimitSeconds;return S.startActiveSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.check`,async n=>{try{let r=Date.now();if(n.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.configured_seconds`,t),!e.lastRequestTimestamp){e.lastRequestTimestamp=r,n.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.action`,`allowed`);return}let i=(r-e.lastRequestTimestamp)/1e3;if(n.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.elapsed_seconds`,i),i>t){e.lastRequestTimestamp=r,n.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.action`,`allowed`);return}let a=Math.ceil(t-i);if(n.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.wait_seconds`,a),!e.rateLimitWait)throw n.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.action`,`rejected`),he.add(1,{action:`rejected`,source:`local`}),w.warn(`Rate limit exceeded. Need to wait ${a} more seconds.`),new o(`Rate limit exceeded`,Response.json({message:`Rate limit exceeded`},{status:429}));let s=a*1e3;n.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.action`,`waited`),he.add(1,{action:`waited`,source:`local`}),ge.record(s,{source:`local`}),w.warn(`Rate limit reached. Waiting ${a} seconds before proceeding...`),await k(s),e.lastRequestTimestamp=r,w.info(`Rate limit wait completed, proceeding with request`)}finally{n.end()}})}function yn(e){let t=e,n=String.fromCodePoint(27),r=t.split(n);if(r.length>1){t=r[0];for(let e=1;e<r.length;e++){let i=r[e],a=i.match(/^\[[0-9;]*[a-z]/i);t+=a?i.slice(a[0].length):n+i}}return t.replaceAll(/[\u200B-\u200D\uFEFF]/g,``).replaceAll(/[\u2060-\u2064]/g,``).replaceAll(/[\u206A-\u206F]/g,``).replaceAll(/[\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/g,``).replaceAll(/[\uFFF0-\uFFFF]/g,``).replaceAll(/[\x00-\x08\v\f\x0E-\x1F]/g,``)}function bn(e){if(typeof e==`string`)return yn(e);if(Array.isArray(e)){let t=e.map(e=>bn(e));return t}if(e&&typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))t[n]=bn(r);return t}return e}const xn=async e=>{if(!b.copilotToken)throw Error(`Service token not found`);let t=bn(e),n=t.messages.some(e=>typeof e.content!=`string`&&e.content?.some(e=>e.type===`image_url`)),r=t.messages.some(e=>[`assistant`,`tool`].includes(e.role)),i={...g(b,n),"X-Initiator":r?`agent`:`user`},a=h(b),s=`${a}/chat/completions`,c=jt(a),l=b.timeoutMs,u=new AbortController,d=setTimeout(()=>u.abort(),l);try{let{statusCode:e,headers:a,body:d,span:f}=await Ee({spanName:`\u0063\u006f\u0070\u0069\u006c\u006f\u0074 POST /chat/completions`,url:s,target:`chat_completions`,headers:i,body:JSON.stringify(t),signal:u.signal,headersTimeout:l,bodyTimeout:l*3,extraAttributes:{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model":t.model,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.streaming":!!t.stream,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.timeout_ms":l,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.has_tools":!!t.tools?.length,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tool_count":t.tools?.length??0,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.message_count":t.messages.length,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.max_tokens":t.max_tokens??0,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.vision_enabled":n,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.initiator":r?`agent`:`user`},dispatcher:c}),p=new Response(d,{status:e,headers:a});if(!p.ok)throw f.end(),new o(`Failed to create chat completions`,p);if(t.stream)return{events:Be(p),span:f,release:()=>V(c)};let m=await p.json();return m.id&&f.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.response.id`,m.id),m.usage&&ln(f,m.usage),f.end(),V(c),m}catch(e){throw V(c),e}finally{clearTimeout(d)}};function Sn(e){return S.startActiveSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model.validate`,t=>{try{t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model.requested`,e.model);let n=_n(e.model);return t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model.normalized`,n),n===e.model?(t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model.was_mapped`,!1),e):(t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model.was_mapped`,!0),de.add(1,{from_model:e.model,to_model:n}),w.debug(`Normalized model from '${e.model}' to '${n}'`),{...e,model:n})}finally{t.end()}})}function Cn(e,t){if(!e.data)return e;try{let n=JSON.parse(e.data);if(n.usage&&t(n.usage),n.usage?.prompt_tokens_details?.cached_tokens!==void 0)return{...e,data:JSON.stringify({...n,usage:{...n.usage,prompt_tokens_details:void 0}})}}catch{}return e}async function wn(t){await vn(b);let n=await t.req.json();w.debug(`Request payload:`,JSON.stringify(n).slice(-400));try{n=Sn(n)}catch(e){if(e instanceof q)return t.json({error:{message:e.message,type:`invalid_request_error`,code:`invalid_model`}},e.statusCode);throw e}if(t.set(`requestData`,{model:n.model,streaming:!!n.stream}),b.manualApprove&&await sn(),Je(n.max_tokens)){let e=b.models?.data.find(e=>e.id===n.model);n={...n,max_tokens:e?.capabilities.limits?.max_output_tokens},w.debug(`Set max_tokens to:`,JSON.stringify(n.max_tokens))}let r=performance.now(),i=await xn(n),a=performance.now()-r;if(ee.record(a,{model:n.model,target:`chat_completions`,streaming:String(!!n.stream)}),Tn(i)){let e=t.get(`requestData`)||{};return i.usage&&(e.tokenUsage=K(i.usage)),e.copilotDuration=a,t.set(`requestData`,e),w.debug(`Non-streaming response:`,JSON.stringify(i)),t.json(i)}let{events:o,span:s,release:c}=i;return O(t,async r=>{let i={value:null},l=0,u=performance.now();try{try{for await(let e of o){let o=e;e.data&&e.data!==`[DONE]`&&(l++,xe.add(1,{model:n.model,endpoint_type:`\u006f\u0070\u0065\u006e\u0061\u0069`}),o=Cn(e,e=>{i.value=e;let n=t.get(`requestData`)||{};n.tokenUsage=K(e),n.copilotDuration=a,t.set(`requestData`,n)})),await r.writeSSE(o)}let e=performance.now()-u,s={model:n.model,endpoint_type:`\u006f\u0070\u0065\u006e\u0061\u0069`};if(Se.record(e,s),p.record(l,s),i.value){let e=t.get(`requestData`)||{};e.tokenUsage||(e.tokenUsage=K(i.value),e.copilotDuration=a,t.set(`requestData`,e))}}finally{i.value&&ln(s,i.value),s.end(),c()}let d=t.get(`requestId`);d&&e.executeCompletion(d)}finally{t.get(`resolveStreamComplete`)?.()}})}const Tn=e=>Object.hasOwn(e,`choices`),En=new D;En.post(`/`,async e=>{try{return await wn(e)}catch(t){return await v(e,t)}});const Dn=async e=>{if(!b.copilotToken)throw Error(`Service token not found`);let t=`${h(b)}/embeddings`,n=g(b),r=b.timeoutMs,i=new AbortController,a=setTimeout(()=>i.abort(),r);try{let{response:r,span:a}=await x({spanName:`\u0063\u006f\u0070\u0069\u006c\u006f\u0074 POST /embeddings`,url:t,target:`embeddings`,method:`POST`,headers:n,body:JSON.stringify(e),signal:i.signal,extraAttributes:{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model":e.model,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.input_count":Array.isArray(e.input)?e.input.length:1}});if(!r.ok)throw a.end(),new o(`Failed to create embeddings`,r);let s=await r.json();return a.end(),s}finally{clearTimeout(a)}},On=new D;On.post(`/`,async e=>{try{let t=await e.req.json();try{_n(t.model)}catch(t){if(t instanceof q)return e.json({error:{message:t.message,type:`invalid_request_error`,code:`invalid_model`}},t.statusCode);throw t}e.set(`requestData`,{model:t.model});let n=performance.now(),r=await Dn(t),i=performance.now()-n;ee.record(i,{model:t.model,target:`embeddings`,streaming:`false`});let a=e.get(`requestData`)||{};return a.tokenUsage=K(r.usage),a.copilotDuration=i,e.set(`requestData`,a),e.json(r)}catch(t){return await v(e,t)}});const kn=new Ve(Ue),An=He[`\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063/\u0063\u006c\u0061\u0075\u0064\u0065-sonnet-4`].tokens,J={...An,baseOverhead:4,perTool:27};function Y(e){return kn.encode(e).length}async function jn(e){let t;try{t=await e.req.json()}catch{return e.json({error:{type:`invalid_request_error`,message:`Invalid JSON`}},400)}if(!Array.isArray(t.messages))return e.json({error:{type:`invalid_request_error`,message:`messages is required`}},400);let n=J.baseOverhead;if(t.system){let e=typeof t.system==`string`?t.system:t.system.map(e=>e.text).join(`
|
|
15
|
-
|
|
16
|
-
`);n+=J.perMessage+Y(e)*J.contentMultiplier}for(let e of t.messages)n+=J.perMessage,n+=Y(e.role),typeof e.content==`string`?n+=Y(e.content)*J.contentMultiplier:Array.isArray(e.content)&&(n+=Mn(e.content));return t.tools&&t.tools.length>0&&(n+=Nn(t.tools)),e.json({input_tokens:Math.round(n)})}function Mn(e){let t=0;for(let n of e)switch(n.type){case`text`:t+=Y(n.text)*J.contentMultiplier;break;case`tool_use`:{let e=n.name+JSON.stringify(n.input);t+=Y(e)*J.contentMultiplier;break}case`tool_result`:n.content&&(t+=Y(typeof n.content==`string`?n.content:JSON.stringify(n.content))*J.contentMultiplier);break;case`thinking`:t+=Y(n.thinking)*J.contentMultiplier;break;case`image`:t+=1600;break}return t}function Nn(e){let t=J.toolsExist;for(let[n,r]of e.entries())n>0&&(t+=J.perTool),t+=Y(r.name),r.description&&(t+=J.perDesc+Y(r.description)),t+=Pn(r.input_schema);return t}function Pn(e){let t=0,n=e.properties;if(!n)return t;let r=Object.entries(n);for(let[e,[n,i]]of r.entries()){if(t+=e===0?J.perFirstProp:J.perAdditionalProp,t+=Y(n),i.description&&(t+=J.perPropDesc+Y(i.description)),i.enum&&Array.isArray(i.enum)){t+=J.perEnum;for(let e of i.enum)t+=Y(String(e))}if(i.type===`object`&&i.properties&&(t+=J.perNestedObject,t+=Pn(i)),i.type===`array`&&i.items){let e=i.items;e.type===`object`&&e.properties&&(t+=J.perArrayOfObjects,t+=Pn(e))}}return t}function Fn(e){if(e===null)return null;let t={stop:`end_turn`,length:`max_tokens`,tool_calls:`tool_use`,content_filter:`end_turn`};return t[e]}function In(e){return{model:Ln(e.model),messages:Rn(e.messages,e.system),max_tokens:e.max_tokens,stop:e.stop_sequences,stream:e.stream,temperature:e.temperature,top_p:e.top_p,user:e.metadata?.user_id,tools:Un(e.tools),tool_choice:Wn(e.tool_choice)}}function Ln(e){return e}function Rn(e,t){let n=Bn(t),r=e.flatMap(e=>e.role===`user`?Vn(e):Hn(e));return[...n,...r]}function zn(e){return e.startsWith(`x-\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063-billing-header`)?e.replace(/^x-anthropic-billing-header:[^\n]*\n+/,``):e}function Bn(e){if(!e)return[];if(typeof e==`string`)return[{role:`system`,content:zn(e)}];{let t=e.map(e=>e.text).join(`
|
|
17
|
-
|
|
18
|
-
`);return[{role:`system`,content:zn(t)}]}}function Vn(e){let t=[];if(Array.isArray(e.content)){let n=e.content.filter(e=>e.type===`tool_result`),r=e.content.filter(e=>e.type!==`tool_result`);for(let e of n)t.push({role:`tool`,tool_call_id:e.tool_use_id,content:X(e.content)});r.length>0&&t.push({role:`user`,content:X(r)})}else t.push({role:`user`,content:X(e.content)});return t}function Hn(e){if(!Array.isArray(e.content))return[{role:`assistant`,content:X(e.content)}];let t=e.content.filter(e=>e.type===`tool_use`),n=e.content.filter(e=>e.type===`text`),r=e.content.filter(e=>e.type===`thinking`),i=[...n.map(e=>e.text),...r.map(e=>e.thinking)].join(`
|
|
19
|
-
|
|
20
|
-
`);return t.length>0?[{role:`assistant`,content:i||null,tool_calls:t.map(e=>({id:e.id,type:`function`,function:{name:e.name,arguments:JSON.stringify(e.input)}}))}]:[{role:`assistant`,content:X(e.content)}]}function X(e){if(typeof e==`string`)return e;if(!Array.isArray(e))return null;let t=e.some(e=>e.type===`image`);if(!t)return e.filter(e=>e.type===`text`||e.type===`thinking`).map(e=>e.type===`text`?e.text:e.thinking).join(`
|
|
21
|
-
|
|
22
|
-
`);let n=[];for(let t of e)switch(t.type){case`text`:n.push({type:`text`,text:t.text});break;case`thinking`:n.push({type:`text`,text:t.thinking});break;case`image`:n.push({type:`image_url`,image_url:{url:`data:${t.source.media_type};base64,${t.source.data}`}});break}return n}function Un(e){if(e)return e.map(e=>({type:`function`,function:{name:e.name,description:e.description,parameters:e.input_schema}}))}function Wn(e){if(e)switch(e.type){case`auto`:return`auto`;case`any`:return`required`;case`tool`:return e.name?{type:`function`,function:{name:e.name}}:void 0;case`none`:return`none`;default:return}}function Gn(e){let t=[],n=[],r=null;r=e.choices[0]?.finish_reason??r;for(let i of e.choices){let e=Kn(i.message.content),a=qn(i.message.tool_calls);t.push(...e),n.push(...a),(i.finish_reason===`tool_calls`||r===`stop`)&&(r=i.finish_reason)}return{id:e.id,type:`message`,role:`assistant`,model:e.model,content:[...t,...n],stop_reason:Fn(r),stop_sequence:null,usage:{input_tokens:e.usage?.prompt_tokens??0,output_tokens:e.usage?.completion_tokens??0}}}function Kn(e){return typeof e==`string`?[{type:`text`,text:e}]:Array.isArray(e)?e.filter(e=>e.type===`text`).map(e=>({type:`text`,text:e.text})):[]}function qn(e){return e?e.map(e=>({type:`tool_use`,id:e.id,name:e.function.name,input:JSON.parse(e.function.arguments)})):[]}function Jn(e){return e.contentBlockOpen?Object.values(e.toolCalls).some(t=>t.anthropicBlockIndex===e.contentBlockIndex):!1}function Yn(e,t){let n=[];if(e.choices.length===0)return n;let r=e.choices[0],{delta:i}=r;if(t.messageStartSent||=(n.push({type:`message_start`,message:{id:e.id,type:`message`,role:`assistant`,content:[],model:e.model,stop_reason:null,stop_sequence:null,usage:{input_tokens:e.usage?.prompt_tokens??0,output_tokens:0}}}),!0),i.content&&(Jn(t)&&(n.push({type:`content_block_stop`,index:t.contentBlockIndex}),t.contentBlockIndex++,t.contentBlockOpen=!1),t.contentBlockOpen||=(n.push({type:`content_block_start`,index:t.contentBlockIndex,content_block:{type:`text`,text:``}}),!0),n.push({type:`content_block_delta`,index:t.contentBlockIndex,delta:{type:`text_delta`,text:i.content}})),i.tool_calls)for(let e of i.tool_calls){if(e.id&&e.function?.name){t.contentBlockOpen&&=(n.push({type:`content_block_stop`,index:t.contentBlockIndex}),t.contentBlockIndex++,!1);let r=t.contentBlockIndex;t.toolCalls[e.index]={id:e.id,name:e.function.name,anthropicBlockIndex:r},n.push({type:`content_block_start`,index:r,content_block:{type:`tool_use`,id:e.id,name:e.function.name,input:{}}}),t.contentBlockOpen=!0}if(e.function?.arguments){let r=t.toolCalls[e.index];r&&n.push({type:`content_block_delta`,index:r.anthropicBlockIndex,delta:{type:`input_json_delta`,partial_json:e.function.arguments}})}}return r.finish_reason&&(t.contentBlockOpen&&=(n.push({type:`content_block_stop`,index:t.contentBlockIndex}),!1),n.push({type:`message_delta`,delta:{stop_reason:Fn(r.finish_reason),stop_sequence:null},usage:{input_tokens:e.usage?.prompt_tokens??0,output_tokens:e.usage?.completion_tokens??0}},{type:`message_stop`})),n}async function Xn(e,t,n){let r={query:t,max_results:n?.maxResults??5};n?.includeDomains?.length&&(r.include_domains=n.includeDomains),n?.excludeDomains?.length&&(r.exclude_domains=n.excludeDomains),w.debug(`Tavily search request:`,JSON.stringify(r));let i=await fetch(`https://api.tavily.com/search`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${e}`},body:JSON.stringify(r)});if(!i.ok){let e=await i.text();throw w.error(`Tavily API error (${i.status}):`,e),Error(`Tavily API error: ${i.status} ${e}`)}let a=await i.json();return w.debug(`Tavily returned ${a.results.length} results`),a.results}function Zn(e){let t=e.tools;if(!t||t.length!==1)return!1;let n=t[0].type;return typeof n==`string`&&n.startsWith(`web_search`)}function Qn(e){let t=e.messages[0];if(!t||t.role!==`user`)return null;let n;if(typeof t.content==`string`)n=t.content;else if(Array.isArray(t.content)){let e=t.content.find(e=>e.type===`text`);if(!e)return null;n=e.text}else return null;return n.startsWith(`Perform a web search for the query: `)?n.slice(36).trim():n.trim()||null}function $n(e){let t=e.tools,n=t?.[0],r=typeof n?.max_uses==`number`?n.max_uses:5;return{maxResults:r,allowedDomains:n?.allowed_domains,blockedDomains:n?.blocked_domains}}function Z(){let e=``;for(let t=0;t<24;t++)e+=`abcdefghijklmnopqrstuvwxyz0123456789`[Math.floor(Math.random()*36)];return e}function er(e){let{query:t,results:n,model:r}=e,i=`srvtoolu_${Z()}`,a=[{type:`text`,text:`I'll search for that.`},{type:`server_tool_use`,id:i,name:`web_search`,input:{query:t}},{type:`web_search_tool_result`,tool_use_id:i,content:n}];return{id:`msg_tavily_${Z()}`,type:`message`,role:`assistant`,model:r,content:a,stop_reason:`end_turn`,stop_sequence:null,usage:{input_tokens:0,output_tokens:0}}}function tr(e){let{query:t,results:n,model:r}=e,i=`srvtoolu_${Z()}`,a=`msg_tavily_${Z()}`,o=[];return o.push({type:`message_start`,message:{id:a,type:`message`,role:`assistant`,content:[],model:r,stop_reason:null,stop_sequence:null,usage:{input_tokens:0,output_tokens:0}}},{type:`content_block_start`,index:0,content_block:{type:`text`,text:``}},{type:`content_block_delta`,index:0,delta:{type:`text_delta`,text:`I'll search for that.`}},{type:`content_block_stop`,index:0},{type:`content_block_start`,index:1,content_block:{type:`server_tool_use`,id:i,name:`web_search`,input:{}}},{type:`content_block_delta`,index:1,delta:{type:`input_json_delta`,partial_json:JSON.stringify({query:t})}},{type:`content_block_stop`,index:1},{type:`content_block_start`,index:2,content_block:{type:`web_search_tool_result`,tool_use_id:i,content:n}},{type:`content_block_stop`,index:2},{type:`message_delta`,delta:{stop_reason:`end_turn`,stop_sequence:null},usage:{output_tokens:0}},{type:`message_stop`}),o}async function nr(e,t){let n=Qn(t);if(!n)return e.json({type:`error`,error:{type:`invalid_request_error`,message:`Could not extract search query from web search request`}},400);let r=$n(t);w.info(`Web search intercepted: "${n}"`);let i=[];try{let e=b.tavilyApiKey;if(!e)throw Error(`No Tavily API key configured`);let t=await Xn(e,n,{maxResults:Math.min(r.maxResults,10),includeDomains:r.allowedDomains,excludeDomains:r.blockedDomains});i=t.map(e=>({type:`web_search_result`,url:e.url,title:e.title,encrypted_content:Buffer.from(e.content).toString(`base64`),page_age:null}))}catch(e){w.error(`Tavily search failed:`,e)}let a={query:n,results:i,model:t.model};if(!t.stream)return e.json(er(a));let o=tr(a);return O(e,async e=>{for(let t of o)await e.writeSSE({event:t.type,data:JSON.stringify(t)})})}function rr(e,t){return S.startActiveSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model.validate`,n=>{try{n.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model.requested`,t.model);let e=_n(t.model);return n.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model.normalized`,e),e===t.model?(n.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model.was_mapped`,!1),t):(n.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model.was_mapped`,!0),de.add(1,{from_model:t.model,to_model:e}),w.debug(`Model mapping: '${t.model}' → '${e}'`),{...t,model:e})}catch(t){if(t instanceof q)return e.json({type:`error`,error:{type:`invalid_request_error`,message:t.message}},t.statusCode),null;throw t}finally{n.end()}})}async function ir(t){let n=await t.req.json();if(Zn(n))return nr(t,n);await vn(b),w.debug(`\u0041\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063 request payload:`,JSON.stringify(n));let r=t.req.header(`\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063-beta`)??``,i=/context-1m/i.test(r);if(i){let e=n.model;n={...n,model:`${n.model}-1m`},w.debug(`Detected context-1m beta flag, rewriting model: '${e}' → '${n.model}'`)}let a=rr(t,n);if(!a)return;n=a;let o=performance.now(),s=S.startActiveSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translate.\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063_to_\u006f\u0070\u0065\u006e\u0061\u0069`,e=>{try{e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.direction`,`\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063_to_\u006f\u0070\u0065\u006e\u0061\u0069`),e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.message_count`,n.messages.length),e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.has_tools`,!!n.tools?.length),e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.has_system`,!!n.system),e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.context_1m_beta`,i);let t=n.messages.some(e=>Array.isArray(e.content)&&e.content.some(e=>e.type===`image`)),r=n.messages.some(e=>Array.isArray(e.content)&&e.content.some(e=>e.type===`thinking`));return e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.has_images`,t),e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.has_thinking`,r),In(n)}finally{e.end()}});De.record(performance.now()-o,{direction:`\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063_to_\u006f\u0070\u0065\u006e\u0061\u0069`}),w.debug(`Translated \u004f\u0070\u0065\u006e\u0041\u0049 request payload:`,JSON.stringify(s)),t.set(`requestData`,{model:s.model,streaming:!!s.stream});let c=performance.now();b.manualApprove&&await sn();let l=await xn(s),u=performance.now()-c;if(ee.record(u,{model:s.model,target:`chat_completions`,streaming:String(!!s.stream)}),ar(l)){let e=t.get(`requestData`)||{};l.usage&&(e.tokenUsage=K(l.usage)),e.copilotDuration=u,t.set(`requestData`,e),w.debug(`Non-streaming response:`,JSON.stringify(l).slice(-400));let n=performance.now(),r=S.startActiveSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translate.\u006f\u0070\u0065\u006e\u0061\u0069_to_\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063`,e=>{try{e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.direction`,`\u006f\u0070\u0065\u006e\u0061\u0069_to_\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063`);let t=Gn(l);return e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.content_blocks`,t.content.length),e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.stop_reason`,t.stop_reason??`null`),e.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.has_tool_use`,t.content.some(e=>e.type===`tool_use`)),t}finally{e.end()}});return De.record(performance.now()-n,{direction:`\u006f\u0070\u0065\u006e\u0061\u0069_to_\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063`}),w.debug(`Translated \u0041\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063 response:`,JSON.stringify(r)),t.json(r)}w.debug(`Streaming response from service`);let{events:d,span:f,release:m}=l;return O(t,async n=>{let r=null,i=0,a=performance.now(),o={messageStartSent:!1,contentBlockIndex:0,contentBlockOpen:!1,toolCalls:{}};try{try{for await(let e of d){if(w.debug(`Raw stream event:`,JSON.stringify(e)),e.data===`[DONE]`)break;if(!e.data)continue;let a=JSON.parse(e.data);if(i++,xe.add(1,{model:s.model,endpoint_type:`\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063`}),a.usage){r=a.usage;let e=t.get(`requestData`)||{};e.tokenUsage=K(r),e.copilotDuration=u,t.set(`requestData`,e)}let c=Yn(a,o);for(let e of c)w.debug(`Translated \u0041\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063 event:`,JSON.stringify(e)),await n.writeSSE({event:e.type,data:JSON.stringify(e)})}let e=performance.now()-a,c={model:s.model,endpoint_type:`\u0061\u006e\u0074\u0068\u0072\u006f\u0070\u0069\u0063`};if(Se.record(e,c),p.record(i,c),r){let e=t.get(`requestData`)||{};e.tokenUsage||(e.tokenUsage=K(r),e.copilotDuration=u,t.set(`requestData`,e))}}finally{r&&ln(f,r),f.end(),m()}let c=t.get(`requestId`);c&&e.executeCompletion(c)}finally{t.get(`resolveStreamComplete`)?.()}})}const ar=e=>Object.hasOwn(e,`choices`),or=new D;or.post(`/`,async e=>{try{return await ir(e)}catch(t){return await v(e,t)}});const sr=new D;sr.get(`/`,async e=>{try{b.models||await Ye();let t=b.models?.data.map(e=>({id:e.id,object:`model`,type:`model`,created:0,created_at:new Date(0).toISOString(),owned_by:e.vendor,display_name:e.name,context_length:e.capabilities.limits?.max_context_window_tokens}));return e.json({object:`list`,data:t,has_more:!1})}catch(t){return await v(e,t)}});const cr=new D;cr.get(`/`,e=>{try{return e.json({token:b.copilotToken})}catch(t){return console.error(`Error fetching token:`,t),e.json({error:`Failed to fetch token`,token:null},500)}});const lr=new D;lr.get(`/`,async e=>{try{let t=await ot();return e.json(t)}catch(t){return console.error(`Error fetching usage:`,t),e.json({error:`Failed to fetch usage`},500)}});const Q=new D;Q.use(on()),Q.use(ze()),Q.get(`/`,e=>e.text(`Server running`)),Q.route(`/chat/completions`,En),Q.route(`/models`,sr),Q.route(`/embeddings`,On),Q.route(`/usage`,lr),Q.route(`/token`,cr),Q.route(`/v1/chat/completions`,En),Q.route(`/v1/models`,sr),Q.route(`/v1/embeddings`,On),Q.route(`/v1/messages`,or),Q.post(`/v1/messages/count_tokens`,jn);const ur=[],$=Date.now();let dr=``;function fr(){let e=async(e,t=0)=>{let n=S.startSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.server.shutdown`,{kind:Ae.INTERNAL,attributes:{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.shutdown.reason":e,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.shutdown.exit_code":t,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.uptime_seconds":(Date.now()-$)/1e3}});for(let e of ur)try{await e()}catch(e){w.error(`Error during cleanup:`,e)}n.end(),$t(dr,Date.now()-$),E.exit(t)};E.on(`SIGINT`,()=>e(`SIGINT`)),E.on(`SIGTERM`,()=>e(`SIGTERM`)),E.on(`uncaughtException`,t=>{w.error(`Uncaught exception:`,t),e(`uncaughtException`,1)}),E.on(`unhandledRejection`,(t,n)=>{w.error(`Unhandled promise rejection at:`,n,`reason:`,t),e(`unhandledRejection`,1)})}async function pr(e,t){if(!e.claudeCode)return!1;Le(b.models,`Models should be loaded by now`);let n,r;if(e.model&&e.smallModel){let t=b.models.data.map(e=>e.id);t.includes(e.model)||(w.error(`Invalid model: ${e.model}`),w.info(`Available services: \n${t.join(`
|
|
23
|
-
`)}`),E.exit(1)),t.includes(e.smallModel)||(w.error(`Invalid small model: ${e.smallModel}`),w.info(`Available services: \n${t.join(`
|
|
24
|
-
`)}`),E.exit(1)),n=e.model,r=e.smallModel}else e.model||e.smallModel?(w.error(`Both --model and --small-model must be specified for model selection`),E.exit(1)):(n=await w.prompt(`Select a model to use`,{type:`select`,options:b.models.data.map(e=>e.id)}),r=await w.prompt(`Select a small model to use`,{type:`select`,options:b.models.data.map(e=>e.id)}));let i=Rt({ANTHROPIC_BASE_URL:t,ANTHROPIC_AUTH_TOKEN:`dummy`,ANTHROPIC_MODEL:n,ANTHROPIC_SMALL_FAST_MODEL:r},`\u0063\u006c\u0061\u0075\u0064\u0065`);try{return Fe.writeSync(i),!0}catch{return w.warn(`Failed to copy to clipboard. Here is the command:`),w.log(i),!1}}function mr(e){let{options:t,version:n,runtime:r,githubUser:i}=e,a=S.startSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.server.startup`,{kind:Ae.INTERNAL,attributes:re({config:{version:n,port:t.port,accountType:t.accountType,verbose:t.verbose,manualApprove:t.manual,rateLimitSeconds:t.rateLimit??0,rateLimitWait:t.rateLimitWait,timeoutMs:t.timeout,showToken:t.showToken,claudeCode:t.claudeCode,disableConnectivityMonitoring:t.disableConnectivityMonitoring,model:t.model,smallModel:t.smallModel,githubTokenSource:t.githubToken?`cli_arg`:`stored`},runtime:r,identity:{githubUser:i.login,machineId:b.machineId,sessionId:b.sessionId,vsCodeVersion:b.vsCodeVersion},connectivity:b.connectivity,modelsCount:b.models?.data.length??0,startupDurationMs:Date.now()-$},`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api`)});if(b.models?.data)for(let e of b.models.data)a.addEvent(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model.available`,re(e,`model`));a.end(),_(l.INFO,`INFO`,`Server started`,re({version:n,port:t.port,accountType:t.accountType,githubUser:i.login,modelsCount:b.models?.data.length??0,startupDurationMs:Date.now()-$},`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api`))}function hr(){let e=E.env.COPILOT_H2_KEEPALIVE===`1`||E.env.COPILOT_H2_KEEPALIVE===`true`,t=e||E.env.COPILOT_H2===`1`||E.env.COPILOT_H2===`true`;b.connectivity.h2=t,b.connectivity.h2Keepalive=e}function gr(){b.connectivity.h2&&(V(jt(h(b))),b.connectivity.h2Keepalive&&Ft())}async function _r(e){fr(),ur.push(()=>{w.debug(`Cleaning up connectivity monitor`),m.stop()},()=>{w.debug(`Cleaning up token management`),Qe()},async()=>{w.debug(`Cleaning up HTTP/2 client`),await It()},async()=>{w.debug(`Shutting down OTel SDK`),await ye()}),e.verbose&&(w.level=5,w.info(`Verbose logging enabled`)),b.accountType=e.accountType,b.manualApprove=e.manual,b.rateLimitSeconds=e.rateLimit,b.rateLimitWait=e.rateLimitWait,b.showToken=e.showToken,b.timeoutMs=e.timeout,b.connectivity.enabled=!e.disableConnectivityMonitoring,e.tavilyApiKey&&(b.tavilyApiKey=e.tavilyApiKey),hr(),await te(),Xe();let t=await ct();dr=t;let n=lt();se(t,$),e.githubToken?(b.githubToken=e.githubToken,w.info(`Using provided Auth token`)):await nt();let r;try{let{_s4:e}=await import(`./get-user-DdXUcoAP.js`);r=await e(),await ce(b,r.login)}catch(e){w.error(`Failed to get user info for machine ID generation:`,e),w.error(`Cannot proceed without user information`),E.exit(1)}await tt(),await Ye(),gr(),mr({options:e,version:t,runtime:n,githubUser:r});let i=`http://localhost:${e.port}`,a=await pr(e,i);Qt({version:t,runtime:n,user:r.login,accountType:e.accountType,port:e.port,timeout:e.timeout,webSearch:!!e.tavilyApiKey,model:e.model,smallModel:e.smallModel,clipboardCopied:a}),Ie({fetch:Q.fetch,port:e.port})}const vr=C({meta:{name:`start`,description:`Start the API server`},args:{port:{alias:`p`,type:`string`,default:`4141`,description:`Port to listen on`},verbose:{alias:`v`,type:`boolean`,default:!1,description:`Enable verbose logging`},"account-type":{alias:`a`,type:`string`,default:`individual`,description:`Account type (individual, business, enterprise)`},manual:{type:`boolean`,default:!1,description:`Enable manual request approval`},"rate-limit":{alias:`r`,type:`string`,description:`Rate limit in seconds between requests`},wait:{alias:`w`,type:`boolean`,default:!1,description:`Wait instead of error when rate limit is hit. Has no effect if rate limit is not set`},"\u0067\u0069\u0074\u0068\u0075\u0062-token":{alias:`g`,type:`string`,description:"Provide auth token directly (must be generated using the `auth` subcommand)"},"\u0063\u006c\u0061\u0075\u0064\u0065-code":{alias:`c`,type:`boolean`,default:!1,description:`Generate a command to launch with API config`},model:{alias:`m`,type:`string`,description:`Model to use (requires --\u0063\u006c\u0061\u0075\u0064\u0065-code)`},"small-model":{alias:`s`,type:`string`,description:`Small/fast model to use (requires --\u0063\u006c\u0061\u0075\u0064\u0065-code)`},"show-token":{type:`boolean`,default:!1,description:`Show tokens on fetch and refresh`},timeout:{alias:`t`,type:`string`,description:`API timeout in milliseconds (default: 600000)`},"disable-connectivity-monitoring":{type:`boolean`,default:!1,description:`Disable automatic network monitoring for token refresh`},"tavily-api-key":{type:`string`,description:`Tavily API key for web search support (or set TAVILY_API_KEY env var)`}},run({args:e}){let n=e[`rate-limit`],r=n===void 0?void 0:Number.parseInt(n,10),i=e.timeout,a=i===void 0?t:Number.parseInt(i,10);return _r({port:Number.parseInt(e.port,10),verbose:e.verbose,accountType:e[`account-type`],manual:e.manual,rateLimit:r,rateLimitWait:e.wait,githubToken:e[`\u0067\u0069\u0074\u0068\u0075\u0062-token`],claudeCode:e[`\u0063\u006c\u0061\u0075\u0064\u0065-code`],model:e.model,smallModel:e[`small-model`],showToken:e[`show-token`],timeout:a,disableConnectivityMonitoring:e[`disable-connectivity-monitoring`],tavilyApiKey:e[`tavily-api-key`]||E.env.TAVILY_API_KEY})}});await Dt();const yr=C({meta:{name:`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`,description:`API proxy server for tool integration.`},subCommands:{auth:at,start:vr,"check-usage":st,debug:ht}});await Oe(yr);export{};
|