ghc-proxy 0.8.0 → 0.8.1

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.
Files changed (3) hide show
  1. package/README.md +6 -6
  2. package/dist/main.mjs +39 -18
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -121,9 +121,9 @@ bunx ghc-proxy@latest selfcheck # Probe the packaged bundle (loads every to
121
121
  | `--idle-timeout` | -- | `120` | Bun server idle timeout in seconds (`0` disables; Bun max is `255`; streaming routes disable idle timeout automatically) |
122
122
  | `--upstream-timeout` | -- | `1800` | Upstream request timeout in seconds (0 to disable) |
123
123
  | `--upstream-queue-concurrency` | -- | `10` | Maximum concurrent Copilot upstream requests |
124
- | `--upstream-queue-retries` | -- | `5` | Maximum retries for upstream 429 responses |
125
- | `--upstream-queue-base-delay` | -- | `2` | Base delay in seconds for upstream 429 backoff when `Retry-After` is absent |
126
- | `--upstream-queue-max-delay` | -- | `60` | Maximum delay in seconds for upstream 429 backoff |
124
+ | `--upstream-queue-retries` | -- | `5` | Maximum retries for transient upstream responses (`408`, `429`, `500`, `502`, `503`, `504`, `529`) |
125
+ | `--upstream-queue-base-delay` | -- | `2` | Base delay in seconds for upstream retry backoff when `Retry-After` is absent |
126
+ | `--upstream-queue-max-delay` | -- | `60` | Maximum delay in seconds for upstream retry backoff |
127
127
  | `--ghe-domain` | `--ghe` | -- | GitHub Enterprise Cloud company domain (e.g. `company.ghe.com`). Required for GHE.com device login on first run; persisted automatically for later runs. |
128
128
 
129
129
  ## Rate Limiting
@@ -206,9 +206,9 @@ All fields are optional. The full schema:
206
206
  | `responsesOfficialEmulatorTtlSeconds` | `number` | `14400` | In-memory TTL for locally emulated Responses state |
207
207
  | `modelReasoningEfforts` | `Record<string, string>` | -- | Per-model reasoning effort defaults for Anthropic-to-Responses translation. Each value must be one of `none`, `minimal`, `low`, `medium`, `high`, or `xhigh` |
208
208
  | `upstreamQueueConcurrency` | `number` | `10` | Maximum concurrent Copilot upstream requests |
209
- | `upstreamQueueMaxRetries` | `number` | `5` | Maximum retries for upstream 429 responses |
210
- | `upstreamQueueBaseDelaySeconds` | `number` | `2` | Base delay (seconds) for upstream 429 backoff when `Retry-After` is absent |
211
- | `upstreamQueueMaxDelaySeconds` | `number` | `60` | Maximum delay (seconds) for upstream 429 backoff |
209
+ | `upstreamQueueMaxRetries` | `number` | `5` | Maximum retries for transient upstream responses (`408`, `429`, `500`, `502`, `503`, `504`, `529`) |
210
+ | `upstreamQueueBaseDelaySeconds` | `number` | `2` | Base delay (seconds) for upstream retry backoff when `Retry-After` is absent |
211
+ | `upstreamQueueMaxDelaySeconds` | `number` | `60` | Maximum delay (seconds) for upstream retry backoff |
212
212
  | `gheDomain` | `string` | -- | GitHub Enterprise Cloud company domain (persisted automatically after GHE.com auth) |
213
213
 
214
214
  Example:
package/dist/main.mjs CHANGED
@@ -5980,6 +5980,31 @@ var HTTPError = class extends Error {
5980
5980
  return Response.json(this.body, { status: this.status });
5981
5981
  }
5982
5982
  };
5983
+ const TRANSIENT_UPSTREAM_STATUSES = new Set([
5984
+ 408,
5985
+ 429,
5986
+ 500,
5987
+ 502,
5988
+ 503,
5989
+ 504,
5990
+ 529
5991
+ ]);
5992
+ /**
5993
+ * Upstream statuses worth retrying: request-scoped faults (timeouts, gateway
5994
+ * errors) plus capacity limits. Shared by `UpstreamRequestQueue` and the
5995
+ * Copilot token refresh so both agree on what "transient" means.
5996
+ */
5997
+ function isTransientUpstreamStatus(status) {
5998
+ return TRANSIENT_UPSTREAM_STATUSES.has(status);
5999
+ }
6000
+ /**
6001
+ * Capacity signals that apply to the whole account or service rather than one
6002
+ * request. Only these warrant global back-pressure — applying a queue-wide
6003
+ * cooldown to a request-scoped 5xx turns one bad request into a proxy stall.
6004
+ */
6005
+ function isCapacityLimitStatus(status) {
6006
+ return status === 429 || status === 529;
6007
+ }
5983
6008
  function throwInvalidRequestError(message, param, code) {
5984
6009
  throw new HTTPError(400, { error: {
5985
6010
  message,
@@ -6014,7 +6039,9 @@ function isStructuredErrorPayload(value) {
6014
6039
  return typeof value === "object" && value !== null && "error" in value && typeof value.error === "object" && value.error !== null;
6015
6040
  }
6016
6041
  function upstreamErrorType(status) {
6017
- return status === 429 ? "rate_limit_error" : "upstream_error";
6042
+ if (status === 429) return "rate_limit_error";
6043
+ if (status === 529) return "overloaded_error";
6044
+ return "upstream_error";
6018
6045
  }
6019
6046
  function createFallbackUpstreamError(message, response, rawText) {
6020
6047
  return { error: {
@@ -6957,8 +6984,10 @@ var UpstreamRequestQueue = class {
6957
6984
  lease.release();
6958
6985
  throw error;
6959
6986
  }
6960
- if (response.status !== 429 || !context.retryable || attempt >= this.options.maxRetries) {
6961
- if (response.status === 429 && !context.retryable) this.applyCooldown(this.getRetryDelayMs(response, 0));
6987
+ const { status } = response;
6988
+ const isCapacityLimit = isCapacityLimitStatus(status);
6989
+ if (!(isTransientUpstreamStatus(status) && context.retryable === true && attempt < this.options.maxRetries)) {
6990
+ if (isCapacityLimit) this.applyCooldown(this.getRetryDelayMs(response, 0));
6962
6991
  return {
6963
6992
  response,
6964
6993
  release: lease.release
@@ -6966,10 +6995,10 @@ var UpstreamRequestQueue = class {
6966
6995
  }
6967
6996
  const delayMs = this.getRetryDelayMs(response, attempt);
6968
6997
  await discardResponse(response);
6998
+ if (isCapacityLimit) this.applyCooldown(delayMs);
6969
6999
  lease.release();
6970
- this.applyCooldown(delayMs);
6971
7000
  this.logger.warn([
6972
- "Upstream rate limited;",
7001
+ `Upstream ${status};`,
6973
7002
  `retrying ${formatRequestContext(context)}`,
6974
7003
  `in ${formatDurationMs(delayMs)}`,
6975
7004
  `(attempt ${attempt + 1}/${this.options.maxRetries})`
@@ -7244,16 +7273,8 @@ async function setupGitHubToken(options) {
7244
7273
  function isAuthError(error) {
7245
7274
  return error instanceof HTTPError && (error.status === 401 || error.status === 403);
7246
7275
  }
7247
- const TRANSIENT_HTTP_STATUSES = new Set([
7248
- 408,
7249
- 429,
7250
- 500,
7251
- 502,
7252
- 503,
7253
- 504
7254
- ]);
7255
7276
  function isTransientHttpError(error) {
7256
- return TRANSIENT_HTTP_STATUSES.has(error.status);
7277
+ return isTransientUpstreamStatus(error.status);
7257
7278
  }
7258
7279
  async function logUser() {
7259
7280
  const user = await createGitHubClient().getGitHubUser();
@@ -7364,7 +7385,7 @@ const checkUsage = defineCommand({
7364
7385
  });
7365
7386
  //#endregion
7366
7387
  //#region src/util/version.ts
7367
- const VERSION = "0.8.0";
7388
+ const VERSION = "0.8.1";
7368
7389
  //#endregion
7369
7390
  //#region src/debug.ts
7370
7391
  function getRuntimeInfo() {
@@ -53194,15 +53215,15 @@ const start = defineCommand({
53194
53215
  },
53195
53216
  "upstream-queue-retries": {
53196
53217
  type: "string",
53197
- description: "Maximum retries for upstream 429 responses (default: 5)"
53218
+ description: "Maximum retries for transient upstream responses (default: 5)"
53198
53219
  },
53199
53220
  "upstream-queue-base-delay": {
53200
53221
  type: "string",
53201
- description: "Base delay in seconds for upstream 429 backoff when Retry-After is absent (default: 2)"
53222
+ description: "Base delay in seconds for upstream retry backoff when Retry-After is absent (default: 2)"
53202
53223
  },
53203
53224
  "upstream-queue-max-delay": {
53204
53225
  type: "string",
53205
- description: "Maximum delay in seconds for upstream 429 backoff (default: 60)"
53226
+ description: "Maximum delay in seconds for upstream retry backoff (default: 60)"
53206
53227
  },
53207
53228
  "ghe-domain": {
53208
53229
  alias: "ghe",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ghc-proxy",
3
3
  "type": "module",
4
- "version": "0.8.0",
4
+ "version": "0.8.1",
5
5
  "description": "GitHub Copilot to OpenAI/Anthropic API proxy - Use Copilot with Claude Code, Cursor, and more",
6
6
  "author": "wxxb789 <wxxb789@outlook.com>",
7
7
  "homepage": "https://github.com/wxxb789/ghc-proxy",
@@ -41,6 +41,7 @@
41
41
  "smoke:cache": "bun run scripts/smoke/cache-control.ts",
42
42
  "smoke:packaged": "bun run scripts/smoke/packaged-cli.ts",
43
43
  "smoke:translation": "bun run scripts/smoke/translation.ts",
44
+ "serve": "NODE_ENV=production bun run ./src/main.ts start --wait --idle-timeout=255 --upstream-timeout=1800",
44
45
  "start": "NODE_ENV=production bun run ./src/main.ts",
45
46
  "typecheck": "npx tsc --project tsconfig.json"
46
47
  },