@hsupu/copilot-api 0.7.7 → 0.7.8
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/dist/main.js +173 -111
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -246,8 +246,8 @@ async function getVSCodeVersion() {
|
|
|
246
246
|
}
|
|
247
247
|
});
|
|
248
248
|
if (!response.ok) return FALLBACK;
|
|
249
|
-
const version = (await response.json()).tag_name;
|
|
250
|
-
if (version && /^\d+\.\d+\.\d+$/.test(version)) return version;
|
|
249
|
+
const version$1 = (await response.json()).tag_name;
|
|
250
|
+
if (version$1 && /^\d+\.\d+\.\d+$/.test(version$1)) return version$1;
|
|
251
251
|
return FALLBACK;
|
|
252
252
|
} catch {
|
|
253
253
|
return FALLBACK;
|
|
@@ -434,13 +434,13 @@ const checkUsage = defineCommand({
|
|
|
434
434
|
const premiumUsed = premiumTotal - premium.remaining;
|
|
435
435
|
const premiumPercentUsed = premiumTotal > 0 ? premiumUsed / premiumTotal * 100 : 0;
|
|
436
436
|
const premiumPercentRemaining = premium.percent_remaining;
|
|
437
|
-
function summarizeQuota(name, snap) {
|
|
438
|
-
if (!snap) return `${name}: N/A`;
|
|
437
|
+
function summarizeQuota(name$1, snap) {
|
|
438
|
+
if (!snap) return `${name$1}: N/A`;
|
|
439
439
|
const total = snap.entitlement;
|
|
440
440
|
const used = total - snap.remaining;
|
|
441
441
|
const percentUsed = total > 0 ? used / total * 100 : 0;
|
|
442
442
|
const percentRemaining = snap.percent_remaining;
|
|
443
|
-
return `${name}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`;
|
|
443
|
+
return `${name$1}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`;
|
|
444
444
|
}
|
|
445
445
|
const premiumLine = `Premium: ${premiumUsed}/${premiumTotal} used (${premiumPercentUsed.toFixed(1)}% used, ${premiumPercentRemaining.toFixed(1)}% remaining)`;
|
|
446
446
|
const chatLine = summarizeQuota("Chat", usage.quota_snapshots.chat);
|
|
@@ -481,9 +481,9 @@ async function checkTokenExists() {
|
|
|
481
481
|
}
|
|
482
482
|
}
|
|
483
483
|
async function getDebugInfo() {
|
|
484
|
-
const [version, tokenExists] = await Promise.all([getPackageVersion(), checkTokenExists()]);
|
|
484
|
+
const [version$1, tokenExists] = await Promise.all([getPackageVersion(), checkTokenExists()]);
|
|
485
485
|
return {
|
|
486
|
-
version,
|
|
486
|
+
version: version$1,
|
|
487
487
|
runtime: getRuntimeInfo(),
|
|
488
488
|
paths: {
|
|
489
489
|
APP_DIR: PATHS.APP_DIR,
|
|
@@ -571,8 +571,8 @@ const PATTERNS = {
|
|
|
571
571
|
/**
|
|
572
572
|
* Parse semver version string to comparable parts
|
|
573
573
|
*/
|
|
574
|
-
function parseVersion(version) {
|
|
575
|
-
return version.split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
574
|
+
function parseVersion(version$1) {
|
|
575
|
+
return version$1.split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
576
576
|
}
|
|
577
577
|
/**
|
|
578
578
|
* Compare two semver versions
|
|
@@ -590,9 +590,9 @@ function compareVersions(a, b) {
|
|
|
590
590
|
}
|
|
591
591
|
return 0;
|
|
592
592
|
}
|
|
593
|
-
function getPatternTypeForVersion(version) {
|
|
594
|
-
if (compareVersions(version, SUPPORTED_VERSIONS.v2a.min) >= 0 && compareVersions(version, SUPPORTED_VERSIONS.v2a.max) <= 0) return "func";
|
|
595
|
-
if (compareVersions(version, SUPPORTED_VERSIONS.v2b.min) >= 0 && compareVersions(version, SUPPORTED_VERSIONS.v2b.max) <= 0) return "variable";
|
|
593
|
+
function getPatternTypeForVersion(version$1) {
|
|
594
|
+
if (compareVersions(version$1, SUPPORTED_VERSIONS.v2a.min) >= 0 && compareVersions(version$1, SUPPORTED_VERSIONS.v2a.max) <= 0) return "func";
|
|
595
|
+
if (compareVersions(version$1, SUPPORTED_VERSIONS.v2b.min) >= 0 && compareVersions(version$1, SUPPORTED_VERSIONS.v2b.max) <= 0) return "variable";
|
|
596
596
|
return null;
|
|
597
597
|
}
|
|
598
598
|
/**
|
|
@@ -624,8 +624,8 @@ function findInVoltaTools(voltaHome) {
|
|
|
624
624
|
if (existsSync(packagesPath)) paths.push(packagesPath);
|
|
625
625
|
const toolsDir = join(voltaHome, "tools", "image", "node");
|
|
626
626
|
if (existsSync(toolsDir)) try {
|
|
627
|
-
for (const version of readdirSync(toolsDir)) {
|
|
628
|
-
const claudePath = join(toolsDir, version, "lib", "node_modules", "@anthropic-ai", "claude-code", "cli.js");
|
|
627
|
+
for (const version$1 of readdirSync(toolsDir)) {
|
|
628
|
+
const claudePath = join(toolsDir, version$1, "lib", "node_modules", "@anthropic-ai", "claude-code", "cli.js");
|
|
629
629
|
if (existsSync(claudePath)) paths.push(claudePath);
|
|
630
630
|
}
|
|
631
631
|
} catch {}
|
|
@@ -668,23 +668,23 @@ function getCurrentLimit(content) {
|
|
|
668
668
|
* Check if Claude Code version is supported for patching
|
|
669
669
|
*/
|
|
670
670
|
function checkVersionSupport(cliPath) {
|
|
671
|
-
const version = getClaudeCodeVersion(cliPath);
|
|
672
|
-
if (!version) return {
|
|
671
|
+
const version$1 = getClaudeCodeVersion(cliPath);
|
|
672
|
+
if (!version$1) return {
|
|
673
673
|
supported: false,
|
|
674
674
|
version: null,
|
|
675
675
|
patternType: null,
|
|
676
676
|
error: "Could not detect Claude Code version"
|
|
677
677
|
};
|
|
678
|
-
const patternType = getPatternTypeForVersion(version);
|
|
678
|
+
const patternType = getPatternTypeForVersion(version$1);
|
|
679
679
|
if (!patternType) return {
|
|
680
680
|
supported: false,
|
|
681
|
-
version,
|
|
681
|
+
version: version$1,
|
|
682
682
|
patternType: null,
|
|
683
|
-
error: `Version ${version} is not supported. Supported: ${getSupportedRangeString()}`
|
|
683
|
+
error: `Version ${version$1} is not supported. Supported: ${getSupportedRangeString()}`
|
|
684
684
|
};
|
|
685
685
|
return {
|
|
686
686
|
supported: true,
|
|
687
|
-
version,
|
|
687
|
+
version: version$1,
|
|
688
688
|
patternType
|
|
689
689
|
};
|
|
690
690
|
}
|
|
@@ -735,8 +735,8 @@ function restoreClaudeCode(cliPath) {
|
|
|
735
735
|
return true;
|
|
736
736
|
}
|
|
737
737
|
function showStatus(cliPath, currentLimit) {
|
|
738
|
-
const version = getClaudeCodeVersion(cliPath);
|
|
739
|
-
if (version) consola.info(`Claude Code version: ${version}`);
|
|
738
|
+
const version$1 = getClaudeCodeVersion(cliPath);
|
|
739
|
+
if (version$1) consola.info(`Claude Code version: ${version$1}`);
|
|
740
740
|
if (currentLimit === null) {
|
|
741
741
|
consola.warn("Could not detect current limit - CLI may have been updated");
|
|
742
742
|
consola.info("Look for the BS9 variable or HR function pattern in cli.js");
|
|
@@ -818,6 +818,86 @@ const patchClaude = defineCommand({
|
|
|
818
818
|
}
|
|
819
819
|
});
|
|
820
820
|
|
|
821
|
+
//#endregion
|
|
822
|
+
//#region package.json
|
|
823
|
+
var name = "@hsupu/copilot-api";
|
|
824
|
+
var version = "0.7.8";
|
|
825
|
+
var description = "Turn GitHub Copilot into OpenAI/Anthropic API compatible server. Usable with Claude Code!";
|
|
826
|
+
var keywords = [
|
|
827
|
+
"proxy",
|
|
828
|
+
"github-copilot",
|
|
829
|
+
"openai-compatible",
|
|
830
|
+
"anthropic-compatible"
|
|
831
|
+
];
|
|
832
|
+
var homepage = "https://github.com/puxu-msft/copilot-api-js";
|
|
833
|
+
var bugs = "https://github.com/puxu-msft/copilot-api-js/issues";
|
|
834
|
+
var repository = {
|
|
835
|
+
"type": "git",
|
|
836
|
+
"url": "git+https://github.com/puxu-msft/copilot-api-js.git"
|
|
837
|
+
};
|
|
838
|
+
var author = "hsupu";
|
|
839
|
+
var type = "module";
|
|
840
|
+
var bin = { "copilot-api": "dist/main.js" };
|
|
841
|
+
var files = ["dist"];
|
|
842
|
+
var scripts = {
|
|
843
|
+
"build": "npx tsdown",
|
|
844
|
+
"dev": "bun run --watch ./src/main.ts",
|
|
845
|
+
"knip": "knip-bun",
|
|
846
|
+
"lint": "eslint --cache",
|
|
847
|
+
"lint:all": "eslint --cache .",
|
|
848
|
+
"prepack": "npm run build",
|
|
849
|
+
"prepare": "npm run build && (command -v bun >/dev/null 2>&1 && simple-git-hooks || true)",
|
|
850
|
+
"release": "bumpp && npm publish --access public",
|
|
851
|
+
"start": "NODE_ENV=production bun run ./src/main.ts",
|
|
852
|
+
"typecheck": "tsc"
|
|
853
|
+
};
|
|
854
|
+
var simple_git_hooks = { "pre-commit": "bun x lint-staged" };
|
|
855
|
+
var lint_staged = { "*": "bun run lint --fix" };
|
|
856
|
+
var dependencies = {
|
|
857
|
+
"citty": "^0.1.6",
|
|
858
|
+
"clipboardy": "^5.0.0",
|
|
859
|
+
"consola": "^3.4.2",
|
|
860
|
+
"fetch-event-stream": "^0.1.5",
|
|
861
|
+
"gpt-tokenizer": "^3.0.1",
|
|
862
|
+
"hono": "^4.9.9",
|
|
863
|
+
"picocolors": "^1.1.1",
|
|
864
|
+
"proxy-from-env": "^1.1.0",
|
|
865
|
+
"srvx": "^0.8.9",
|
|
866
|
+
"tiny-invariant": "^1.3.3",
|
|
867
|
+
"undici": "^7.16.0"
|
|
868
|
+
};
|
|
869
|
+
var devDependencies = {
|
|
870
|
+
"@echristian/eslint-config": "^0.0.54",
|
|
871
|
+
"@types/bun": "^1.2.23",
|
|
872
|
+
"@types/proxy-from-env": "^1.0.4",
|
|
873
|
+
"bumpp": "^10.2.3",
|
|
874
|
+
"eslint": "^9.37.0",
|
|
875
|
+
"knip": "^5.64.1",
|
|
876
|
+
"lint-staged": "^16.2.3",
|
|
877
|
+
"prettier-plugin-packagejson": "^2.5.19",
|
|
878
|
+
"simple-git-hooks": "^2.13.1",
|
|
879
|
+
"tsdown": "^0.15.6",
|
|
880
|
+
"typescript": "^5.9.3"
|
|
881
|
+
};
|
|
882
|
+
var package_default = {
|
|
883
|
+
name,
|
|
884
|
+
version,
|
|
885
|
+
description,
|
|
886
|
+
keywords,
|
|
887
|
+
homepage,
|
|
888
|
+
bugs,
|
|
889
|
+
repository,
|
|
890
|
+
author,
|
|
891
|
+
type,
|
|
892
|
+
bin,
|
|
893
|
+
files,
|
|
894
|
+
scripts,
|
|
895
|
+
"simple-git-hooks": simple_git_hooks,
|
|
896
|
+
"lint-staged": lint_staged,
|
|
897
|
+
dependencies,
|
|
898
|
+
devDependencies
|
|
899
|
+
};
|
|
900
|
+
|
|
821
901
|
//#endregion
|
|
822
902
|
//#region src/lib/adaptive-rate-limiter.ts
|
|
823
903
|
const DEFAULT_CONFIG$1 = {
|
|
@@ -1566,8 +1646,8 @@ var ConsoleRenderer = class {
|
|
|
1566
1646
|
/**
|
|
1567
1647
|
* Get log prefix based on log type
|
|
1568
1648
|
*/
|
|
1569
|
-
getLogPrefix(type) {
|
|
1570
|
-
switch (type) {
|
|
1649
|
+
getLogPrefix(type$1) {
|
|
1650
|
+
switch (type$1) {
|
|
1571
1651
|
case "error":
|
|
1572
1652
|
case "fatal": return pc.red("✖");
|
|
1573
1653
|
case "warn": return pc.yellow("⚠");
|
|
@@ -2183,18 +2263,40 @@ function getToolUseIds(message) {
|
|
|
2183
2263
|
return [];
|
|
2184
2264
|
}
|
|
2185
2265
|
/**
|
|
2186
|
-
*
|
|
2187
|
-
* Returns the starting index of messages to preserve.
|
|
2266
|
+
* Estimate the byte size of a message (for binary search).
|
|
2188
2267
|
*/
|
|
2189
|
-
function
|
|
2190
|
-
|
|
2191
|
-
|
|
2268
|
+
function estimateMessageBytes(message) {
|
|
2269
|
+
return JSON.stringify(message).length;
|
|
2270
|
+
}
|
|
2271
|
+
/**
|
|
2272
|
+
* Find the optimal preserve index using binary search.
|
|
2273
|
+
* This finds the point where we keep as many messages as possible
|
|
2274
|
+
* while staying under both token and byte limits.
|
|
2275
|
+
*/
|
|
2276
|
+
function findOptimalPreserveIndex(messages, systemMessages, targetTokens, targetBytes) {
|
|
2277
|
+
if (messages.length === 0) return 0;
|
|
2278
|
+
const systemTokens = systemMessages.reduce((sum, msg) => sum + estimateMessageTokens(msg), 0);
|
|
2279
|
+
const systemBytes = systemMessages.reduce((sum, msg) => sum + estimateMessageBytes(msg), 0);
|
|
2280
|
+
const markerOverhead = 200;
|
|
2281
|
+
const availableTokens = targetTokens - systemTokens - markerOverhead / 4;
|
|
2282
|
+
const availableBytes = targetBytes - systemBytes - markerOverhead;
|
|
2283
|
+
const cumulativeTokens = Array.from({ length: messages.length + 1 }, () => 0);
|
|
2284
|
+
const cumulativeBytes = Array.from({ length: messages.length + 1 }, () => 0);
|
|
2192
2285
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2193
|
-
const
|
|
2194
|
-
|
|
2195
|
-
|
|
2286
|
+
const msg = messages[i];
|
|
2287
|
+
cumulativeTokens[i] = cumulativeTokens[i + 1] + estimateMessageTokens(msg);
|
|
2288
|
+
cumulativeBytes[i] = cumulativeBytes[i + 1] + estimateMessageBytes(msg);
|
|
2196
2289
|
}
|
|
2197
|
-
|
|
2290
|
+
let left = 0;
|
|
2291
|
+
let right = messages.length;
|
|
2292
|
+
while (left < right) {
|
|
2293
|
+
const mid = Math.floor((left + right) / 2);
|
|
2294
|
+
const tokensFromMid = cumulativeTokens[mid];
|
|
2295
|
+
const bytesFromMid = cumulativeBytes[mid];
|
|
2296
|
+
if (tokensFromMid <= availableTokens && bytesFromMid <= availableBytes) right = mid;
|
|
2297
|
+
else left = mid + 1;
|
|
2298
|
+
}
|
|
2299
|
+
return left;
|
|
2198
2300
|
}
|
|
2199
2301
|
/**
|
|
2200
2302
|
* Filter out orphaned tool_result messages that don't have a matching tool_use
|
|
@@ -2232,12 +2334,6 @@ function ensureStartsWithUser(messages) {
|
|
|
2232
2334
|
return messages.slice(startIndex);
|
|
2233
2335
|
}
|
|
2234
2336
|
/**
|
|
2235
|
-
* Calculate estimated tokens for system messages.
|
|
2236
|
-
*/
|
|
2237
|
-
function estimateSystemTokens(systemMessages) {
|
|
2238
|
-
return systemMessages.reduce((sum, msg) => sum + estimateMessageTokens(msg), 0);
|
|
2239
|
-
}
|
|
2240
|
-
/**
|
|
2241
2337
|
* Create a truncation marker message.
|
|
2242
2338
|
*/
|
|
2243
2339
|
function createTruncationMarker(removedCount) {
|
|
@@ -2248,8 +2344,9 @@ function createTruncationMarker(removedCount) {
|
|
|
2248
2344
|
}
|
|
2249
2345
|
/**
|
|
2250
2346
|
* Perform auto-compaction on a payload that exceeds token or size limits.
|
|
2251
|
-
* This uses simple truncation - no LLM calls required.
|
|
2252
|
-
*
|
|
2347
|
+
* This uses simple truncation with binary search - no LLM calls required.
|
|
2348
|
+
* The algorithm finds the optimal truncation point to maximize preserved messages
|
|
2349
|
+
* while staying under both token and byte limits.
|
|
2253
2350
|
*/
|
|
2254
2351
|
async function autoCompact(payload, model, config = {}) {
|
|
2255
2352
|
const cfg = {
|
|
@@ -2276,58 +2373,20 @@ async function autoCompact(payload, model, config = {}) {
|
|
|
2276
2373
|
else reason = "tokens";
|
|
2277
2374
|
consola.info(`Auto-compact: Exceeds ${reason} limit (${originalTokens} tokens, ${Math.round(originalBytes / 1024)}KB), truncating...`);
|
|
2278
2375
|
const { systemMessages, remainingMessages } = extractSystemMessages(payload.messages);
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
let lastResult = null;
|
|
2285
|
-
for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {
|
|
2286
|
-
const result = await tryCompactWithTarget({
|
|
2376
|
+
consola.debug(`Auto-compact: ${systemMessages.length} system messages, ${remainingMessages.length} conversation messages`);
|
|
2377
|
+
const preserveIndex = findOptimalPreserveIndex(remainingMessages, systemMessages, tokenLimit, byteLimit);
|
|
2378
|
+
if (preserveIndex === 0) {
|
|
2379
|
+
consola.warn("Auto-compact: Cannot truncate without losing all conversation history");
|
|
2380
|
+
return {
|
|
2287
2381
|
payload,
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
limit: tokenLimit,
|
|
2294
|
-
originalTokens
|
|
2295
|
-
});
|
|
2296
|
-
if (!result.wasCompacted) return result;
|
|
2297
|
-
lastResult = result;
|
|
2298
|
-
const resultBytes = JSON.stringify(result.payload).length;
|
|
2299
|
-
const underTokenLimit = result.compactedTokens <= tokenLimit;
|
|
2300
|
-
const underByteLimit = resultBytes <= byteLimit;
|
|
2301
|
-
if (underTokenLimit && underByteLimit) {
|
|
2302
|
-
consola.info(`Auto-compact: ${originalTokens} → ${result.compactedTokens} tokens, ${Math.round(originalBytes / 1024)}KB → ${Math.round(resultBytes / 1024)}KB (removed ${result.removedMessageCount} messages)`);
|
|
2303
|
-
return result;
|
|
2304
|
-
}
|
|
2305
|
-
const tokenStatus = underTokenLimit ? "OK" : `${result.compactedTokens} > ${tokenLimit}`;
|
|
2306
|
-
const byteStatus = underByteLimit ? "OK" : `${Math.round(resultBytes / 1024)}KB > ${Math.round(byteLimit / 1024)}KB`;
|
|
2307
|
-
consola.warn(`Auto-compact: Still over limit (tokens: ${tokenStatus}, size: ${byteStatus}), trying more aggressive truncation`);
|
|
2308
|
-
currentTarget = Math.floor(currentTarget * .7);
|
|
2309
|
-
if (currentTarget < MIN_TARGET) {
|
|
2310
|
-
consola.error("Auto-compact: Cannot reduce further, target too low");
|
|
2311
|
-
return result;
|
|
2312
|
-
}
|
|
2382
|
+
wasCompacted: false,
|
|
2383
|
+
originalTokens,
|
|
2384
|
+
compactedTokens: originalTokens,
|
|
2385
|
+
removedMessageCount: 0
|
|
2386
|
+
};
|
|
2313
2387
|
}
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
payload,
|
|
2317
|
-
wasCompacted: false,
|
|
2318
|
-
originalTokens,
|
|
2319
|
-
compactedTokens: originalTokens,
|
|
2320
|
-
removedMessageCount: 0
|
|
2321
|
-
};
|
|
2322
|
-
}
|
|
2323
|
-
/**
|
|
2324
|
-
* Helper to attempt compaction with a specific target token count.
|
|
2325
|
-
*/
|
|
2326
|
-
async function tryCompactWithTarget(opts) {
|
|
2327
|
-
const { payload, model, systemMessages, remainingMessages, systemTokens, targetTokens, originalTokens } = opts;
|
|
2328
|
-
const preserveIndex = findPreserveIndex(remainingMessages, targetTokens, systemTokens);
|
|
2329
|
-
if (preserveIndex === 0) {
|
|
2330
|
-
consola.warn("Auto-compact: Cannot truncate further without losing all conversation history");
|
|
2388
|
+
if (preserveIndex >= remainingMessages.length) {
|
|
2389
|
+
consola.warn("Auto-compact: Would need to remove all messages, cannot compact");
|
|
2331
2390
|
return {
|
|
2332
2391
|
payload,
|
|
2333
2392
|
wasCompacted: false,
|
|
@@ -2362,6 +2421,8 @@ async function tryCompactWithTarget(opts) {
|
|
|
2362
2421
|
]
|
|
2363
2422
|
};
|
|
2364
2423
|
const newTokenCount = await getTokenCount(newPayload, model);
|
|
2424
|
+
const newBytes = JSON.stringify(newPayload).length;
|
|
2425
|
+
consola.info(`Auto-compact: ${originalTokens} → ${newTokenCount.input} tokens, ${Math.round(originalBytes / 1024)}KB → ${Math.round(newBytes / 1024)}KB (removed ${removedMessages.length} messages)`);
|
|
2365
2426
|
return {
|
|
2366
2427
|
payload: newPayload,
|
|
2367
2428
|
wasCompacted: true,
|
|
@@ -2633,7 +2694,7 @@ function handleNonStreamingResponse$1(c, originalResponse, ctx) {
|
|
|
2633
2694
|
...choice$1,
|
|
2634
2695
|
message: {
|
|
2635
2696
|
...choice$1.message,
|
|
2636
|
-
content: (choice$1.message.content ?? "")
|
|
2697
|
+
content: marker + (choice$1.message.content ?? "")
|
|
2637
2698
|
}
|
|
2638
2699
|
} : choice$1)
|
|
2639
2700
|
};
|
|
@@ -2694,18 +2755,13 @@ async function handleStreamingResponse$1(opts) {
|
|
|
2694
2755
|
const { stream, response, payload, ctx } = opts;
|
|
2695
2756
|
const acc = createStreamAccumulator();
|
|
2696
2757
|
try {
|
|
2697
|
-
for await (const chunk of response) {
|
|
2698
|
-
consola.debug("Streaming chunk:", JSON.stringify(chunk));
|
|
2699
|
-
parseStreamChunk(chunk, acc);
|
|
2700
|
-
await stream.writeSSE(chunk);
|
|
2701
|
-
}
|
|
2702
2758
|
if (ctx.compactResult?.wasCompacted) {
|
|
2703
2759
|
const marker = createCompactionMarker(ctx.compactResult);
|
|
2704
2760
|
const markerChunk = {
|
|
2705
2761
|
id: `compact-marker-${Date.now()}`,
|
|
2706
2762
|
object: "chat.completion.chunk",
|
|
2707
2763
|
created: Math.floor(Date.now() / 1e3),
|
|
2708
|
-
model:
|
|
2764
|
+
model: payload.model,
|
|
2709
2765
|
choices: [{
|
|
2710
2766
|
index: 0,
|
|
2711
2767
|
delta: { content: marker },
|
|
@@ -2719,6 +2775,11 @@ async function handleStreamingResponse$1(opts) {
|
|
|
2719
2775
|
});
|
|
2720
2776
|
acc.content += marker;
|
|
2721
2777
|
}
|
|
2778
|
+
for await (const chunk of response) {
|
|
2779
|
+
consola.debug("Streaming chunk:", JSON.stringify(chunk));
|
|
2780
|
+
parseStreamChunk(chunk, acc);
|
|
2781
|
+
await stream.writeSSE(chunk);
|
|
2782
|
+
}
|
|
2722
2783
|
recordStreamSuccess(acc, payload.model, ctx);
|
|
2723
2784
|
completeTracking(ctx.trackingId, acc.inputTokens, acc.outputTokens, ctx.queueWaitMs);
|
|
2724
2785
|
} catch (error) {
|
|
@@ -4509,7 +4570,7 @@ function handleNonStreamingResponse(opts) {
|
|
|
4509
4570
|
consola.debug("Translated Anthropic response:", JSON.stringify(anthropicResponse));
|
|
4510
4571
|
if (ctx.compactResult?.wasCompacted) {
|
|
4511
4572
|
const marker = createCompactionMarker(ctx.compactResult);
|
|
4512
|
-
anthropicResponse =
|
|
4573
|
+
anthropicResponse = prependMarkerToAnthropicResponse(anthropicResponse, marker);
|
|
4513
4574
|
}
|
|
4514
4575
|
recordResponse(ctx.historyId, {
|
|
4515
4576
|
success: true,
|
|
@@ -4541,16 +4602,16 @@ function handleNonStreamingResponse(opts) {
|
|
|
4541
4602
|
});
|
|
4542
4603
|
return c.json(anthropicResponse);
|
|
4543
4604
|
}
|
|
4544
|
-
function
|
|
4605
|
+
function prependMarkerToAnthropicResponse(response, marker) {
|
|
4545
4606
|
const content = [...response.content];
|
|
4546
|
-
const
|
|
4547
|
-
if (
|
|
4548
|
-
const textBlock = content[
|
|
4549
|
-
if (textBlock.type === "text") content[
|
|
4607
|
+
const firstTextIndex = content.findIndex((block) => block.type === "text");
|
|
4608
|
+
if (firstTextIndex !== -1) {
|
|
4609
|
+
const textBlock = content[firstTextIndex];
|
|
4610
|
+
if (textBlock.type === "text") content[firstTextIndex] = {
|
|
4550
4611
|
...textBlock,
|
|
4551
|
-
text: textBlock.text
|
|
4612
|
+
text: marker + textBlock.text
|
|
4552
4613
|
};
|
|
4553
|
-
} else content.
|
|
4614
|
+
} else content.unshift({
|
|
4554
4615
|
type: "text",
|
|
4555
4616
|
text: marker
|
|
4556
4617
|
});
|
|
@@ -4580,6 +4641,11 @@ async function handleStreamingResponse(opts) {
|
|
|
4580
4641
|
};
|
|
4581
4642
|
const acc = createAnthropicStreamAccumulator();
|
|
4582
4643
|
try {
|
|
4644
|
+
if (ctx.compactResult?.wasCompacted) {
|
|
4645
|
+
const marker = createCompactionMarker(ctx.compactResult);
|
|
4646
|
+
await sendCompactionMarkerEvent(stream, streamState, marker);
|
|
4647
|
+
acc.content += marker;
|
|
4648
|
+
}
|
|
4583
4649
|
await processStreamChunks({
|
|
4584
4650
|
stream,
|
|
4585
4651
|
response,
|
|
@@ -4587,11 +4653,6 @@ async function handleStreamingResponse(opts) {
|
|
|
4587
4653
|
streamState,
|
|
4588
4654
|
acc
|
|
4589
4655
|
});
|
|
4590
|
-
if (ctx.compactResult?.wasCompacted) {
|
|
4591
|
-
const marker = createCompactionMarker(ctx.compactResult);
|
|
4592
|
-
await sendCompactionMarkerEvent(stream, streamState, marker);
|
|
4593
|
-
acc.content += marker;
|
|
4594
|
-
}
|
|
4595
4656
|
recordStreamingResponse(acc, anthropicPayload.model, ctx);
|
|
4596
4657
|
completeTracking(ctx.trackingId, acc.inputTokens, acc.outputTokens, ctx.queueWaitMs);
|
|
4597
4658
|
} catch (error) {
|
|
@@ -4904,6 +4965,7 @@ function formatModelInfo(model) {
|
|
|
4904
4965
|
return ` - ${model.id.padEnd(28)} context: ${contextK.padStart(5)}, output: ${outputK.padStart(4)}${featureStr}`;
|
|
4905
4966
|
}
|
|
4906
4967
|
async function runServer(options) {
|
|
4968
|
+
consola.info(`copilot-api v${package_default.version}`);
|
|
4907
4969
|
if (options.proxyEnv) initProxyFromEnv();
|
|
4908
4970
|
if (options.verbose) {
|
|
4909
4971
|
consola.level = 5;
|