@hsupu/copilot-api 0.7.9 → 0.7.10
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 +115 -47
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -558,15 +558,12 @@ const SUPPORTED_VERSIONS = {
|
|
|
558
558
|
min: "2.0.0",
|
|
559
559
|
max: "2.1.10"
|
|
560
560
|
},
|
|
561
|
-
v2b: {
|
|
562
|
-
min: "2.1.11",
|
|
563
|
-
max: "2.1.12"
|
|
564
|
-
}
|
|
561
|
+
v2b: { min: "2.1.11" }
|
|
565
562
|
};
|
|
566
563
|
const PATTERNS = {
|
|
567
564
|
funcOriginal: /function HR\(A\)\{if\(A\.includes\("\[1m\]"\)\)return 1e6;return 200000\}/,
|
|
568
565
|
funcPatched: /function HR\(A\)\{if\(A\.includes\("\[1m\]"\)\)return 1e6;return \d+\}/,
|
|
569
|
-
variable: /var
|
|
566
|
+
variable: /var ([A-Za-z_$]\w*)=(\d+)(?=,\w+=20000,)/
|
|
570
567
|
};
|
|
571
568
|
/**
|
|
572
569
|
* Parse semver version string to comparable parts
|
|
@@ -592,14 +589,14 @@ function compareVersions(a, b) {
|
|
|
592
589
|
}
|
|
593
590
|
function getPatternTypeForVersion(version$1) {
|
|
594
591
|
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
|
|
592
|
+
if (compareVersions(version$1, SUPPORTED_VERSIONS.v2b.min) >= 0) return "variable";
|
|
596
593
|
return null;
|
|
597
594
|
}
|
|
598
595
|
/**
|
|
599
596
|
* Get supported version range string for error messages
|
|
600
597
|
*/
|
|
601
598
|
function getSupportedRangeString() {
|
|
602
|
-
return `${SUPPORTED_VERSIONS.v2a.min}-${SUPPORTED_VERSIONS.v2a.max}, ${SUPPORTED_VERSIONS.v2b.min}
|
|
599
|
+
return `${SUPPORTED_VERSIONS.v2a.min}-${SUPPORTED_VERSIONS.v2a.max}, ${SUPPORTED_VERSIONS.v2b.min}+`;
|
|
603
600
|
}
|
|
604
601
|
/**
|
|
605
602
|
* Get Claude Code version from package.json
|
|
@@ -632,9 +629,9 @@ function findInVoltaTools(voltaHome) {
|
|
|
632
629
|
return paths;
|
|
633
630
|
}
|
|
634
631
|
/**
|
|
635
|
-
* Find Claude Code CLI
|
|
632
|
+
* Find all Claude Code CLI paths by checking common locations
|
|
636
633
|
*/
|
|
637
|
-
function
|
|
634
|
+
function findAllClaudeCodePaths() {
|
|
638
635
|
const possiblePaths = [];
|
|
639
636
|
const home = process.env.HOME || "";
|
|
640
637
|
const voltaHome = process.env.VOLTA_HOME || join(home, ".volta");
|
|
@@ -649,22 +646,41 @@ function findClaudeCodePath() {
|
|
|
649
646
|
for (const base of globalPaths) possiblePaths.push(join(base, "@anthropic-ai", "claude-code", "cli.js"));
|
|
650
647
|
const bunGlobal = join(home, ".bun", "install", "global");
|
|
651
648
|
if (existsSync(bunGlobal)) possiblePaths.push(join(bunGlobal, "node_modules", "@anthropic-ai", "claude-code", "cli.js"));
|
|
652
|
-
return possiblePaths.
|
|
649
|
+
return [...new Set(possiblePaths.filter((p) => existsSync(p)))];
|
|
653
650
|
}
|
|
654
651
|
/**
|
|
655
|
-
* Get
|
|
652
|
+
* Get installation info for a CLI path
|
|
656
653
|
*/
|
|
657
|
-
function
|
|
654
|
+
function getInstallationInfo(cliPath) {
|
|
655
|
+
const version$1 = getClaudeCodeVersion(cliPath);
|
|
656
|
+
const content = readFileSync(cliPath, "utf8");
|
|
657
|
+
const limit = getCurrentLimit(content);
|
|
658
|
+
return {
|
|
659
|
+
path: cliPath,
|
|
660
|
+
version: version$1,
|
|
661
|
+
limit
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
function getCurrentLimitInfo(content) {
|
|
658
665
|
const varMatch = content.match(PATTERNS.variable);
|
|
659
|
-
if (varMatch) return
|
|
666
|
+
if (varMatch) return {
|
|
667
|
+
limit: Number.parseInt(varMatch[2], 10),
|
|
668
|
+
varName: varMatch[1]
|
|
669
|
+
};
|
|
660
670
|
const funcMatch = content.match(PATTERNS.funcPatched);
|
|
661
671
|
if (funcMatch) {
|
|
662
672
|
const limitMatch = funcMatch[0].match(/return (\d+)\}$/);
|
|
663
|
-
return limitMatch ? Number.parseInt(limitMatch[1], 10) : null;
|
|
673
|
+
return limitMatch ? { limit: Number.parseInt(limitMatch[1], 10) } : null;
|
|
664
674
|
}
|
|
665
675
|
return null;
|
|
666
676
|
}
|
|
667
677
|
/**
|
|
678
|
+
* Get current context limit from Claude Code (legacy wrapper)
|
|
679
|
+
*/
|
|
680
|
+
function getCurrentLimit(content) {
|
|
681
|
+
return getCurrentLimitInfo(content)?.limit ?? null;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
668
684
|
* Check if Claude Code version is supported for patching
|
|
669
685
|
*/
|
|
670
686
|
function checkVersionSupport(cliPath) {
|
|
@@ -696,22 +712,25 @@ function patchClaudeCode(cliPath, newLimit) {
|
|
|
696
712
|
const versionCheck = checkVersionSupport(cliPath);
|
|
697
713
|
if (!versionCheck.supported) {
|
|
698
714
|
consola.error(versionCheck.error);
|
|
699
|
-
return
|
|
715
|
+
return "failed";
|
|
700
716
|
}
|
|
701
717
|
consola.info(`Claude Code version: ${versionCheck.version}`);
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
return true;
|
|
705
|
-
}
|
|
718
|
+
const limitInfo = getCurrentLimitInfo(content);
|
|
719
|
+
if (limitInfo?.limit === newLimit) return "already_patched";
|
|
706
720
|
let newContent;
|
|
707
|
-
if (versionCheck.patternType === "variable")
|
|
708
|
-
|
|
721
|
+
if (versionCheck.patternType === "variable") {
|
|
722
|
+
if (!limitInfo?.varName) {
|
|
723
|
+
consola.error("Could not detect variable name for patching");
|
|
724
|
+
return "failed";
|
|
725
|
+
}
|
|
726
|
+
newContent = content.replace(PATTERNS.variable, `var ${limitInfo.varName}=${newLimit}`);
|
|
727
|
+
} else {
|
|
709
728
|
const replacement = `function HR(A){if(A.includes("[1m]"))return 1e6;return ${newLimit}}`;
|
|
710
729
|
const pattern = PATTERNS.funcOriginal.test(content) ? PATTERNS.funcOriginal : PATTERNS.funcPatched;
|
|
711
730
|
newContent = content.replace(pattern, replacement);
|
|
712
731
|
}
|
|
713
732
|
writeFileSync(cliPath, newContent);
|
|
714
|
-
return
|
|
733
|
+
return "success";
|
|
715
734
|
}
|
|
716
735
|
/**
|
|
717
736
|
* Restore Claude Code to original 200k limit
|
|
@@ -724,13 +743,19 @@ function restoreClaudeCode(cliPath) {
|
|
|
724
743
|
return false;
|
|
725
744
|
}
|
|
726
745
|
consola.info(`Claude Code version: ${versionCheck.version}`);
|
|
727
|
-
|
|
746
|
+
const limitInfo = getCurrentLimitInfo(content);
|
|
747
|
+
if (limitInfo?.limit === 2e5) {
|
|
728
748
|
consola.info("Already at original 200000 limit");
|
|
729
749
|
return true;
|
|
730
750
|
}
|
|
731
751
|
let newContent;
|
|
732
|
-
if (versionCheck.patternType === "variable")
|
|
733
|
-
|
|
752
|
+
if (versionCheck.patternType === "variable") {
|
|
753
|
+
if (!limitInfo?.varName) {
|
|
754
|
+
consola.error("Could not detect variable name for restoring");
|
|
755
|
+
return false;
|
|
756
|
+
}
|
|
757
|
+
newContent = content.replace(PATTERNS.variable, `var ${limitInfo.varName}=200000`);
|
|
758
|
+
} else newContent = content.replace(PATTERNS.funcPatched, "function HR(A){if(A.includes(\"[1m]\"))return 1e6;return 200000}");
|
|
734
759
|
writeFileSync(cliPath, newContent);
|
|
735
760
|
return true;
|
|
736
761
|
}
|
|
@@ -739,7 +764,7 @@ function showStatus(cliPath, currentLimit) {
|
|
|
739
764
|
if (version$1) consola.info(`Claude Code version: ${version$1}`);
|
|
740
765
|
if (currentLimit === null) {
|
|
741
766
|
consola.warn("Could not detect current limit - CLI may have been updated");
|
|
742
|
-
consola.info("Look for
|
|
767
|
+
consola.info("Look for a variable like 'var XXX=200000' followed by ',YYY=20000,' in cli.js");
|
|
743
768
|
} else if (currentLimit === 2e5) consola.info("Status: Original (200k context window)");
|
|
744
769
|
else consola.info(`Status: Patched (${currentLimit} context window)`);
|
|
745
770
|
}
|
|
@@ -773,17 +798,42 @@ const patchClaude = defineCommand({
|
|
|
773
798
|
description: "Show current patch status without modifying"
|
|
774
799
|
}
|
|
775
800
|
},
|
|
776
|
-
run({ args }) {
|
|
777
|
-
|
|
778
|
-
if (
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
801
|
+
async run({ args }) {
|
|
802
|
+
let cliPath;
|
|
803
|
+
if (args.path) {
|
|
804
|
+
cliPath = args.path;
|
|
805
|
+
if (!existsSync(cliPath)) {
|
|
806
|
+
consola.error(`File not found: ${cliPath}`);
|
|
807
|
+
process.exit(1);
|
|
808
|
+
}
|
|
809
|
+
} else {
|
|
810
|
+
const installations = findAllClaudeCodePaths();
|
|
811
|
+
if (installations.length === 0) {
|
|
812
|
+
consola.error("Could not find Claude Code installation");
|
|
813
|
+
consola.info("Searched in: volta, npm global, bun global");
|
|
814
|
+
consola.info("Use --path to specify the path to cli.js manually");
|
|
815
|
+
process.exit(1);
|
|
816
|
+
}
|
|
817
|
+
if (installations.length === 1) cliPath = installations[0];
|
|
818
|
+
else {
|
|
819
|
+
consola.info(`Found ${installations.length} Claude Code installations:`);
|
|
820
|
+
const options = installations.map((path$1) => {
|
|
821
|
+
const info = getInstallationInfo(path$1);
|
|
822
|
+
let status = "unknown";
|
|
823
|
+
if (info.limit === 2e5) status = "original";
|
|
824
|
+
else if (info.limit) status = `patched: ${info.limit}`;
|
|
825
|
+
return {
|
|
826
|
+
label: `v${info.version ?? "?"} (${status}) - ${path$1}`,
|
|
827
|
+
value: path$1
|
|
828
|
+
};
|
|
829
|
+
});
|
|
830
|
+
const selected = await consola.prompt("Select installation to patch:", {
|
|
831
|
+
type: "select",
|
|
832
|
+
options
|
|
833
|
+
});
|
|
834
|
+
if (typeof selected === "symbol") process.exit(0);
|
|
835
|
+
cliPath = selected;
|
|
836
|
+
}
|
|
787
837
|
}
|
|
788
838
|
consola.info(`Claude Code path: ${cliPath}`);
|
|
789
839
|
const content = readFileSync(cliPath, "utf8");
|
|
@@ -806,13 +856,14 @@ const patchClaude = defineCommand({
|
|
|
806
856
|
consola.error("Invalid limit value. Must be a number >= 1000");
|
|
807
857
|
process.exit(1);
|
|
808
858
|
}
|
|
809
|
-
|
|
810
|
-
|
|
859
|
+
const result = patchClaudeCode(cliPath, limit);
|
|
860
|
+
if (result === "success") {
|
|
861
|
+
consola.success(`Patched context window: ${currentLimit ?? 2e5} → ${limit}`);
|
|
811
862
|
consola.info("Note: You may need to re-run this after Claude Code updates");
|
|
812
|
-
} else {
|
|
863
|
+
} else if (result === "already_patched") consola.success(`Already patched with limit ${limit}`);
|
|
864
|
+
else {
|
|
813
865
|
consola.error("Failed to patch - pattern not found");
|
|
814
866
|
consola.info("Claude Code may have been updated to a new version");
|
|
815
|
-
consola.info("Check the cli.js for the HR function pattern");
|
|
816
867
|
process.exit(1);
|
|
817
868
|
}
|
|
818
869
|
}
|
|
@@ -821,7 +872,7 @@ const patchClaude = defineCommand({
|
|
|
821
872
|
//#endregion
|
|
822
873
|
//#region package.json
|
|
823
874
|
var name = "@hsupu/copilot-api";
|
|
824
|
-
var version = "0.7.
|
|
875
|
+
var version = "0.7.10";
|
|
825
876
|
var description = "Turn GitHub Copilot into OpenAI/Anthropic API compatible server. Usable with Claude Code!";
|
|
826
877
|
var keywords = [
|
|
827
878
|
"proxy",
|
|
@@ -4109,16 +4160,33 @@ function translateAnthropicMessagesToOpenAI(anthropicMessages, system, toolNameM
|
|
|
4109
4160
|
const otherMessages = anthropicMessages.flatMap((message) => message.role === "user" ? handleUserMessage(message) : handleAssistantMessage(message, toolNameMapping));
|
|
4110
4161
|
return [...systemMessages, ...otherMessages];
|
|
4111
4162
|
}
|
|
4163
|
+
const RESERVED_KEYWORDS = ["x-anthropic-billing-header"];
|
|
4164
|
+
/**
|
|
4165
|
+
* Filter out reserved keywords from system prompt text.
|
|
4166
|
+
* Copilot API rejects requests containing these keywords.
|
|
4167
|
+
* Removes the entire line containing the keyword to keep the prompt clean.
|
|
4168
|
+
*/
|
|
4169
|
+
function filterReservedKeywords(text) {
|
|
4170
|
+
let filtered = text;
|
|
4171
|
+
for (const keyword of RESERVED_KEYWORDS) if (text.includes(keyword)) {
|
|
4172
|
+
consola.debug(`[Reserved Keyword] Removing line containing "${keyword}"`);
|
|
4173
|
+
filtered = filtered.split("\n").filter((line) => !line.includes(keyword)).join("\n");
|
|
4174
|
+
}
|
|
4175
|
+
return filtered;
|
|
4176
|
+
}
|
|
4112
4177
|
function handleSystemPrompt(system) {
|
|
4113
4178
|
if (!system) return [];
|
|
4114
4179
|
if (typeof system === "string") return [{
|
|
4115
4180
|
role: "system",
|
|
4116
|
-
content: system
|
|
4117
|
-
}];
|
|
4118
|
-
else return [{
|
|
4119
|
-
role: "system",
|
|
4120
|
-
content: system.map((block) => block.text).join("\n\n")
|
|
4181
|
+
content: filterReservedKeywords(system)
|
|
4121
4182
|
}];
|
|
4183
|
+
else {
|
|
4184
|
+
const systemText = system.map((block) => block.text).join("\n\n");
|
|
4185
|
+
return [{
|
|
4186
|
+
role: "system",
|
|
4187
|
+
content: filterReservedKeywords(systemText)
|
|
4188
|
+
}];
|
|
4189
|
+
}
|
|
4122
4190
|
}
|
|
4123
4191
|
function handleUserMessage(message) {
|
|
4124
4192
|
const newMessages = [];
|