@dianshuv/copilot-api 0.4.1 → 0.4.3
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 +11 -1
- package/dist/main.mjs +21 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,10 +61,11 @@ copilot-api start
|
|
|
61
61
|
| `--proxy-env` | Use proxy from environment | false |
|
|
62
62
|
| `--no-history` | Disable request history UI at `/history` | false |
|
|
63
63
|
| `--history-limit` | Max history entries in memory | 1000 |
|
|
64
|
-
| `--no-auto-truncate` | Disable auto-truncate when exceeding limits | false |
|
|
64
|
+
| `--no-auto-truncate` | Disable auto-truncate when exceeding token limits | false |
|
|
65
65
|
| `--compress-tool-results` | Compress old tool results before truncating | false |
|
|
66
66
|
| `--redirect-anthropic` | Force Anthropic through OpenAI translation | false |
|
|
67
67
|
| `--no-rewrite-anthropic-tools` | Don't rewrite server-side tools | false |
|
|
68
|
+
| `--timezone-offset` | Timezone offset in hours from UTC for log timestamps (e.g., +8, -5, 0) | +8 |
|
|
68
69
|
|
|
69
70
|
### Patch-Claude Command Options
|
|
70
71
|
|
|
@@ -105,6 +106,15 @@ copilot-api start
|
|
|
105
106
|
| `/history` | GET | Request history Web UI with token analytics (enabled by default) |
|
|
106
107
|
| `/history/api/*` | GET/DELETE | History API endpoints |
|
|
107
108
|
|
|
109
|
+
## Auto-Truncate
|
|
110
|
+
|
|
111
|
+
When enabled (default), auto-truncate automatically compacts conversation history when it exceeds the model's token limit. This prevents request failures due to context overflow.
|
|
112
|
+
|
|
113
|
+
- **Token-based truncation**: Uses the model's `max_context_window_tokens` from the Copilot API to determine when truncation is needed. A 2% safety margin is applied.
|
|
114
|
+
- **No preset byte limit**: There is no hardcoded request body size limit. If the Copilot API returns a 413 (Request Entity Too Large), the proxy dynamically learns the byte limit and applies it to subsequent requests.
|
|
115
|
+
- **Smart compression**: With `--compress-tool-results`, old tool results are compressed before removing messages, preserving more conversation context.
|
|
116
|
+
- **Orphan filtering**: After truncation, orphaned tool results (without matching tool calls) are automatically removed.
|
|
117
|
+
|
|
108
118
|
## Using with Claude Code
|
|
109
119
|
|
|
110
120
|
Create `.claude/settings.json` in your project:
|
package/dist/main.mjs
CHANGED
|
@@ -52,6 +52,7 @@ const state = {
|
|
|
52
52
|
redirectAnthropic: false,
|
|
53
53
|
rewriteAnthropicTools: true,
|
|
54
54
|
staleRequestMaxAge: 600,
|
|
55
|
+
timezoneOffset: 8,
|
|
55
56
|
shutdownGracefulWait: 60,
|
|
56
57
|
shutdownAbortWait: 120
|
|
57
58
|
};
|
|
@@ -105,7 +106,7 @@ const GITHUB_APP_SCOPES = ["read:user"].join(" ");
|
|
|
105
106
|
*/
|
|
106
107
|
const DEFAULT_AUTO_TRUNCATE_CONFIG = {
|
|
107
108
|
safetyMarginPercent: 2,
|
|
108
|
-
maxRequestBodyBytes:
|
|
109
|
+
maxRequestBodyBytes: Infinity,
|
|
109
110
|
preserveRecentPercent: .7
|
|
110
111
|
};
|
|
111
112
|
/** Dynamic byte limit that adjusts based on 413 errors */
|
|
@@ -1020,7 +1021,7 @@ const patchClaude = defineCommand({
|
|
|
1020
1021
|
|
|
1021
1022
|
//#endregion
|
|
1022
1023
|
//#region package.json
|
|
1023
|
-
var version = "0.4.
|
|
1024
|
+
var version = "0.4.3";
|
|
1024
1025
|
|
|
1025
1026
|
//#endregion
|
|
1026
1027
|
//#region src/lib/adaptive-rate-limiter.ts
|
|
@@ -2199,7 +2200,8 @@ function setupShutdownHandlers() {
|
|
|
2199
2200
|
//#region src/lib/tui/console-renderer.ts
|
|
2200
2201
|
const CLEAR_LINE = "\x1B[2K\r";
|
|
2201
2202
|
function formatTime(date = /* @__PURE__ */ new Date()) {
|
|
2202
|
-
|
|
2203
|
+
const adjusted = new Date(date.getTime() + state.timezoneOffset * 60 * 60 * 1e3);
|
|
2204
|
+
return `${String(adjusted.getUTCHours()).padStart(2, "0")}:${String(adjusted.getUTCMinutes()).padStart(2, "0")}:${String(adjusted.getUTCSeconds()).padStart(2, "0")}`;
|
|
2203
2205
|
}
|
|
2204
2206
|
function formatDuration(ms) {
|
|
2205
2207
|
if (ms < 1e3) return `${ms}ms`;
|
|
@@ -3519,7 +3521,7 @@ async function buildFinalPayload(payload, model) {
|
|
|
3519
3521
|
}
|
|
3520
3522
|
try {
|
|
3521
3523
|
const check = await checkNeedsCompactionOpenAI(payload, model);
|
|
3522
|
-
consola.debug(`Auto-truncate check: ${check.currentTokens} tokens (limit ${check.tokenLimit}), ${Math.round(check.currentBytes / 1024)}KB (limit ${Math.round(check.byteLimit / 1024)}KB), needed: ${check.needed}${check.reason ? ` (${check.reason})` : ""}`);
|
|
3524
|
+
consola.debug(`Auto-truncate check: ${check.currentTokens} tokens (limit ${check.tokenLimit}), ${Math.round(check.currentBytes / 1024)}KB (limit ${check.byteLimit === Infinity ? "unlimited" : `${Math.round(check.byteLimit / 1024)}KB`}), needed: ${check.needed}${check.reason ? ` (${check.reason})` : ""}`);
|
|
3523
3525
|
if (!check.needed) return {
|
|
3524
3526
|
finalPayload: payload,
|
|
3525
3527
|
truncateResult: null
|
|
@@ -6736,7 +6738,7 @@ async function handleDirectAnthropicCompletion(c, anthropicPayload, ctx, initiat
|
|
|
6736
6738
|
let truncateResult;
|
|
6737
6739
|
if (state.autoTruncate && selectedModel) {
|
|
6738
6740
|
const check = await checkNeedsCompactionAnthropic(anthropicPayload, selectedModel);
|
|
6739
|
-
consola.debug(`[Anthropic] Auto-truncate check: ${check.currentTokens} tokens (limit ${check.tokenLimit}), ${Math.round(check.currentBytes / 1024)}KB (limit ${Math.round(check.byteLimit / 1024)}KB), needed: ${check.needed}${check.reason ? ` (${check.reason})` : ""}`);
|
|
6741
|
+
consola.debug(`[Anthropic] Auto-truncate check: ${check.currentTokens} tokens (limit ${check.tokenLimit}), ${Math.round(check.currentBytes / 1024)}KB (limit ${check.byteLimit === Infinity ? "unlimited" : `${Math.round(check.byteLimit / 1024)}KB`}), needed: ${check.needed}${check.reason ? ` (${check.reason})` : ""}`);
|
|
6740
6742
|
if (check.needed) try {
|
|
6741
6743
|
truncateResult = await autoTruncateAnthropic(anthropicPayload, selectedModel);
|
|
6742
6744
|
if (truncateResult.wasCompacted) effectivePayload = truncateResult.payload;
|
|
@@ -7815,6 +7817,7 @@ async function runServer(options) {
|
|
|
7815
7817
|
state.compressToolResults = options.compressToolResults;
|
|
7816
7818
|
state.redirectAnthropic = options.redirectAnthropic;
|
|
7817
7819
|
state.rewriteAnthropicTools = options.rewriteAnthropicTools;
|
|
7820
|
+
state.timezoneOffset = options.timezoneOffset;
|
|
7818
7821
|
if (options.rateLimit) initAdaptiveRateLimiter({
|
|
7819
7822
|
baseRetryIntervalSeconds: options.retryInterval,
|
|
7820
7823
|
requestIntervalSeconds: options.requestInterval,
|
|
@@ -7879,6 +7882,12 @@ async function runServer(options) {
|
|
|
7879
7882
|
hostname: options.host
|
|
7880
7883
|
}));
|
|
7881
7884
|
}
|
|
7885
|
+
function parseTimezoneOffset(value) {
|
|
7886
|
+
if (typeof value !== "string") return 8;
|
|
7887
|
+
const n = Number(value);
|
|
7888
|
+
if (!Number.isFinite(n)) return 8;
|
|
7889
|
+
return n;
|
|
7890
|
+
}
|
|
7882
7891
|
const start = defineCommand({
|
|
7883
7892
|
meta: {
|
|
7884
7893
|
name: "start",
|
|
@@ -7988,6 +7997,11 @@ const start = defineCommand({
|
|
|
7988
7997
|
type: "boolean",
|
|
7989
7998
|
default: false,
|
|
7990
7999
|
description: "Don't rewrite Anthropic server-side tools (web_search, etc.) to custom tool format"
|
|
8000
|
+
},
|
|
8001
|
+
"timezone-offset": {
|
|
8002
|
+
type: "string",
|
|
8003
|
+
default: "+8",
|
|
8004
|
+
description: "Timezone offset in hours from UTC for log timestamps (e.g., +8, -5, 0)"
|
|
7991
8005
|
}
|
|
7992
8006
|
},
|
|
7993
8007
|
run({ args }) {
|
|
@@ -8011,7 +8025,8 @@ const start = defineCommand({
|
|
|
8011
8025
|
autoTruncate: !args["no-auto-truncate"],
|
|
8012
8026
|
compressToolResults: args["compress-tool-results"],
|
|
8013
8027
|
redirectAnthropic: args["redirect-anthropic"],
|
|
8014
|
-
rewriteAnthropicTools: !args["no-rewrite-anthropic-tools"]
|
|
8028
|
+
rewriteAnthropicTools: !args["no-rewrite-anthropic-tools"],
|
|
8029
|
+
timezoneOffset: parseTimezoneOffset(args["timezone-offset"])
|
|
8015
8030
|
});
|
|
8016
8031
|
}
|
|
8017
8032
|
});
|