claudebox 0.1.0
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/LICENSE +28 -0
- package/README.md +33 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +202 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +43 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +138 -0
- package/dist/config.js.map +1 -0
- package/dist/converter.d.ts +21 -0
- package/dist/converter.d.ts.map +1 -0
- package/dist/converter.js +159 -0
- package/dist/converter.js.map +1 -0
- package/dist/logger.d.ts +5 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +73 -0
- package/dist/logger.js.map +1 -0
- package/dist/providers/gemini.d.ts +22 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +45 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +4 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/ollama.d.ts +22 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +44 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai.d.ts +22 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +38 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +73 -0
- package/dist/server.js.map +1 -0
- package/dist/translator.d.ts +3 -0
- package/dist/translator.d.ts.map +1 -0
- package/dist/translator.js +155 -0
- package/dist/translator.js.map +1 -0
- package/dist/types.d.ts +108 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, Himanshu
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# claude-code-proxy
|
|
2
|
+
|
|
3
|
+
> Use Claude Code with **any** AI provider: OpenAI, Gemini, or Ollama.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install globally
|
|
9
|
+
npm install -g claudeproxy
|
|
10
|
+
|
|
11
|
+
# configure
|
|
12
|
+
ccproxy configure
|
|
13
|
+
|
|
14
|
+
# start server
|
|
15
|
+
ccproxy server
|
|
16
|
+
|
|
17
|
+
# run claude instance using proxy
|
|
18
|
+
ccproxy
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Development
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
git clone https://github.com/himasnhu-at/ccproxy
|
|
25
|
+
cd ccproxy
|
|
26
|
+
pnpm install
|
|
27
|
+
pnpm build
|
|
28
|
+
pnpm link --global
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## License
|
|
32
|
+
|
|
33
|
+
BSD 3-Clause License
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { spawn as sp } from "node:child_process";
|
|
5
|
+
import { config } from "./config.js";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import figlet from "figlet";
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const { version } = require("../package.json");
|
|
10
|
+
console.log(chalk.cyan(figlet.textSync("ccproxy", {
|
|
11
|
+
font: "Standard",
|
|
12
|
+
horizontalLayout: "default",
|
|
13
|
+
})));
|
|
14
|
+
console.log(chalk.dim(` v${version}\n`));
|
|
15
|
+
// IMP: Add npm update check here in the future (e.g. using update-notifier)
|
|
16
|
+
const args = process.argv.slice(2);
|
|
17
|
+
const command = args[0];
|
|
18
|
+
const options = {
|
|
19
|
+
port: { type: "string", short: "p" },
|
|
20
|
+
provider: { type: "string" },
|
|
21
|
+
"big-model": { type: "string" },
|
|
22
|
+
"small-model": { type: "string" },
|
|
23
|
+
"ollama-base": { type: "string" },
|
|
24
|
+
"openai-key": { type: "string" },
|
|
25
|
+
"gemini-key": { type: "string" },
|
|
26
|
+
verbose: { type: "string", short: "v" },
|
|
27
|
+
help: { type: "boolean", short: "h" },
|
|
28
|
+
};
|
|
29
|
+
const { values } = parseArgs({
|
|
30
|
+
args: args,
|
|
31
|
+
options,
|
|
32
|
+
strict: false,
|
|
33
|
+
allowPositionals: true,
|
|
34
|
+
});
|
|
35
|
+
if (values.help) {
|
|
36
|
+
printHelp();
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
function printHelp() {
|
|
40
|
+
console.log(`
|
|
41
|
+
ccproxy - Use Claude Code with any AI provider
|
|
42
|
+
|
|
43
|
+
USAGE
|
|
44
|
+
ccproxy [command] [options]
|
|
45
|
+
|
|
46
|
+
COMMANDS
|
|
47
|
+
server Start the proxy server
|
|
48
|
+
config Manage configuration (API keys, models, etc.)
|
|
49
|
+
(default) Check if server is running, then start 'claude'
|
|
50
|
+
|
|
51
|
+
OPTIONS
|
|
52
|
+
-p, --port <port> Port to listen on (default: 8082)
|
|
53
|
+
--provider <name> Preferred provider: openai | gemini | ollama
|
|
54
|
+
--big-model <model> Model for sonnet/large requests
|
|
55
|
+
--small-model <model> Model for haiku/small requests
|
|
56
|
+
--ollama-base <url> Ollama base URL
|
|
57
|
+
--openai-key <key> OpenAI API key
|
|
58
|
+
--gemini-key <key> Gemini API key
|
|
59
|
+
-v, --verbose <0|1|2> Logging level: 0=normal, 1=flow, 2=full JSON
|
|
60
|
+
-h, --help Show this help
|
|
61
|
+
|
|
62
|
+
EXAMPLES
|
|
63
|
+
# Set configuration
|
|
64
|
+
ccproxy config --provider gemini --gemini-key AIza...
|
|
65
|
+
|
|
66
|
+
# Start the server with flow logging
|
|
67
|
+
ccproxy server -v 1
|
|
68
|
+
|
|
69
|
+
# Start Claude (after starting server)
|
|
70
|
+
ccproxy
|
|
71
|
+
`);
|
|
72
|
+
}
|
|
73
|
+
async function isServerRunning(port) {
|
|
74
|
+
try {
|
|
75
|
+
const res = await fetch(`http://localhost:${port}/health`);
|
|
76
|
+
return res.ok;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function getUpdatesFromArgs() {
|
|
83
|
+
const updates = {};
|
|
84
|
+
if (values.port)
|
|
85
|
+
updates.port = parseInt(values.port, 10);
|
|
86
|
+
if (values.provider)
|
|
87
|
+
updates.preferredProvider = values.provider;
|
|
88
|
+
let vLevel = undefined;
|
|
89
|
+
const vVal = values.verbose;
|
|
90
|
+
if (vVal !== undefined) {
|
|
91
|
+
if (vVal === "true")
|
|
92
|
+
vLevel = 1;
|
|
93
|
+
else if (vVal === "0" || vVal === "1" || vVal === "2")
|
|
94
|
+
vLevel = parseInt(vVal, 10);
|
|
95
|
+
}
|
|
96
|
+
// Fallback: manual scan to handle shell flag mangling (e.g. -v without value)
|
|
97
|
+
for (let i = 0; i < args.length; i++) {
|
|
98
|
+
const arg = args[i];
|
|
99
|
+
if (arg === "-v" || arg === "--v" || arg === "-verbose" || arg === "--verbose") {
|
|
100
|
+
const next = args[i + 1];
|
|
101
|
+
if (next && (next === "0" || next === "1" || next === "2")) {
|
|
102
|
+
vLevel = parseInt(next, 10);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
vLevel = 1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (vLevel !== undefined)
|
|
110
|
+
updates.verbose = vLevel;
|
|
111
|
+
const providers = {};
|
|
112
|
+
const targetProvider = values.provider ?? config.preferredProvider;
|
|
113
|
+
if (values["big-model"] ||
|
|
114
|
+
values["small-model"] ||
|
|
115
|
+
values["ollama-base"] ||
|
|
116
|
+
values["openai-key"] ||
|
|
117
|
+
values["gemini-key"]) {
|
|
118
|
+
providers[targetProvider] = {};
|
|
119
|
+
const bigModel = values["big-model"];
|
|
120
|
+
const smallModel = values["small-model"];
|
|
121
|
+
const ollamaBase = values["ollama-base"];
|
|
122
|
+
const openaiKey = values["openai-key"];
|
|
123
|
+
const geminiKey = values["gemini-key"];
|
|
124
|
+
if (typeof bigModel === "string")
|
|
125
|
+
providers[targetProvider].bigModel = bigModel;
|
|
126
|
+
if (typeof smallModel === "string")
|
|
127
|
+
providers[targetProvider].smallModel = smallModel;
|
|
128
|
+
if (typeof ollamaBase === "string")
|
|
129
|
+
providers[targetProvider].apiBase = ollamaBase;
|
|
130
|
+
if (typeof openaiKey === "string")
|
|
131
|
+
providers[targetProvider].apiKey = openaiKey;
|
|
132
|
+
if (typeof geminiKey === "string")
|
|
133
|
+
providers[targetProvider].apiKey = geminiKey;
|
|
134
|
+
updates.providers = providers;
|
|
135
|
+
}
|
|
136
|
+
return updates;
|
|
137
|
+
}
|
|
138
|
+
if (command === "config") {
|
|
139
|
+
const updates = getUpdatesFromArgs();
|
|
140
|
+
if (Object.keys(updates).length > 0) {
|
|
141
|
+
config.save(updates);
|
|
142
|
+
console.log("✅ Configuration updated.");
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
console.log("Current Configuration:");
|
|
146
|
+
console.log(JSON.stringify(config.summary(), null, 2));
|
|
147
|
+
}
|
|
148
|
+
process.exit(0);
|
|
149
|
+
}
|
|
150
|
+
if (command === "server") {
|
|
151
|
+
const updates = getUpdatesFromArgs();
|
|
152
|
+
if (Object.keys(updates).length > 0) {
|
|
153
|
+
if (updates.preferredProvider)
|
|
154
|
+
config.preferredProvider = updates.preferredProvider;
|
|
155
|
+
if (updates.port)
|
|
156
|
+
config.port = updates.port;
|
|
157
|
+
if (updates.verbose !== undefined)
|
|
158
|
+
config.verbose = updates.verbose;
|
|
159
|
+
if (updates.providers) {
|
|
160
|
+
for (const p in updates.providers) {
|
|
161
|
+
const prov = p;
|
|
162
|
+
config.providers[prov] = {
|
|
163
|
+
...config.providers[prov],
|
|
164
|
+
...updates.providers[p],
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
await import("./server.js");
|
|
170
|
+
}
|
|
171
|
+
else if (!command || command === "claude") {
|
|
172
|
+
const running = await isServerRunning(config.port);
|
|
173
|
+
if (!running) {
|
|
174
|
+
console.log(`\n❌ Proxy server is not running on port ${config.port}.`);
|
|
175
|
+
console.log(`👉 Run 'ccproxy server' in another terminal first.\n`);
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
console.log(`🚀 Connecting to ccproxy on port ${config.port}...`);
|
|
179
|
+
try {
|
|
180
|
+
const claude = sp("claude", {
|
|
181
|
+
env: {
|
|
182
|
+
...process.env,
|
|
183
|
+
ANTHROPIC_BASE_URL: `http://localhost:${config.port}`,
|
|
184
|
+
},
|
|
185
|
+
stdio: "inherit",
|
|
186
|
+
shell: true,
|
|
187
|
+
});
|
|
188
|
+
claude.on("exit", (code) => {
|
|
189
|
+
process.exit(code ?? 0);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
catch (e) {
|
|
193
|
+
console.error("Failed to start 'claude' CLI. Is it installed?");
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
console.log(`Unknown command: ${command}`);
|
|
199
|
+
printHelp();
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type Provider = "openai" | "gemini" | "ollama";
|
|
2
|
+
interface ProviderConfig {
|
|
3
|
+
apiKey?: string;
|
|
4
|
+
apiBase?: string;
|
|
5
|
+
bigModel?: string;
|
|
6
|
+
smallModel?: string;
|
|
7
|
+
}
|
|
8
|
+
interface ConfigSchema {
|
|
9
|
+
preferredProvider?: Provider;
|
|
10
|
+
providers?: Record<string, ProviderConfig>;
|
|
11
|
+
port?: number;
|
|
12
|
+
verbose?: number;
|
|
13
|
+
}
|
|
14
|
+
declare class Config {
|
|
15
|
+
preferredProvider: Provider;
|
|
16
|
+
providers: Record<Provider, ProviderConfig>;
|
|
17
|
+
port: number;
|
|
18
|
+
verbose: number;
|
|
19
|
+
readonly openaiModels: Set<string>;
|
|
20
|
+
readonly geminiModels: Set<string>;
|
|
21
|
+
readonly ollamaModels: Set<string>;
|
|
22
|
+
constructor();
|
|
23
|
+
get bigModel(): string;
|
|
24
|
+
get smallModel(): string;
|
|
25
|
+
get openaiApiKey(): string;
|
|
26
|
+
get geminiApiKey(): string;
|
|
27
|
+
get ollamaApiBase(): string;
|
|
28
|
+
private loadFromFile;
|
|
29
|
+
save(updates: ConfigSchema): void;
|
|
30
|
+
isOpenAIModel(model: string): boolean;
|
|
31
|
+
isGeminiModel(model: string): boolean;
|
|
32
|
+
isOllamaModel(model: string): boolean;
|
|
33
|
+
resolveProvider(model: string): Provider;
|
|
34
|
+
summary(): {
|
|
35
|
+
preferredProvider: Provider;
|
|
36
|
+
port: number;
|
|
37
|
+
verbose: number;
|
|
38
|
+
providers: Record<Provider, ProviderConfig>;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export declare const config: Config;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAyBtD,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,YAAY;IACpB,iBAAiB,CAAC,EAAE,QAAQ,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,cAAM,MAAM;IACV,iBAAiB,EAAE,QAAQ,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAEhB,QAAQ,CAAC,YAAY,cAAiB;IACtC,QAAQ,CAAC,YAAY,cAAiB;IACtC,QAAQ,CAAC,YAAY,cAAiB;;IAqCtC,IAAI,QAAQ,IAAI,MAAM,CAA6D;IACnF,IAAI,UAAU,IAAI,MAAM,CAA+D;IACvF,IAAI,YAAY,IAAI,MAAM,CAA0C;IACpE,IAAI,YAAY,IAAI,MAAM,CAA0C;IACpE,IAAI,aAAa,IAAI,MAAM,CAA2C;IAEtE,OAAO,CAAC,YAAY;IAYpB,IAAI,CAAC,OAAO,EAAE,YAAY;IA+B1B,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIrC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIrC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIrC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ;IAOxC,OAAO;;;;;;CAQR;AAED,eAAO,MAAM,MAAM,QAAe,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
const CONFIG_DIR = path.join(os.homedir(), ".ccproxy");
|
|
5
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
6
|
+
const OPENAI_MODELS = new Set([
|
|
7
|
+
"o3-mini", "o1", "o1-mini", "o1-pro",
|
|
8
|
+
"gpt-4.5-preview", "gpt-4o", "gpt-4o-audio-preview",
|
|
9
|
+
"chatgpt-4o-latest", "gpt-4o-mini", "gpt-4o-mini-audio-preview",
|
|
10
|
+
"gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano",
|
|
11
|
+
]);
|
|
12
|
+
const GEMINI_MODELS = new Set([
|
|
13
|
+
"gemini-2.5-pro", "gemini-2.5-flash",
|
|
14
|
+
"gemini-2.5-pro-preview-03-25", "gemini-2.0-flash",
|
|
15
|
+
"gemini-1.5-pro", "gemini-1.5-flash",
|
|
16
|
+
]);
|
|
17
|
+
const OLLAMA_MODELS = new Set([
|
|
18
|
+
"llama3.3", "llama3.2", "llama3.1", "llama3",
|
|
19
|
+
"mistral", "mixtral", "codellama", "phi4", "phi3",
|
|
20
|
+
"deepseek-r1", "deepseek-coder", "qwen2.5", "qwen2",
|
|
21
|
+
"gemma3", "gemma2",
|
|
22
|
+
]);
|
|
23
|
+
class Config {
|
|
24
|
+
preferredProvider;
|
|
25
|
+
providers;
|
|
26
|
+
port;
|
|
27
|
+
verbose;
|
|
28
|
+
openaiModels = OPENAI_MODELS;
|
|
29
|
+
geminiModels = GEMINI_MODELS;
|
|
30
|
+
ollamaModels = OLLAMA_MODELS;
|
|
31
|
+
constructor() {
|
|
32
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
33
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
const fileConfig = this.loadFromFile();
|
|
36
|
+
const isNewConfig = !fs.existsSync(CONFIG_FILE) || Object.keys(fileConfig).length === 0;
|
|
37
|
+
this.preferredProvider = fileConfig.preferredProvider ?? "openai";
|
|
38
|
+
this.port = fileConfig.port ?? 8082;
|
|
39
|
+
this.verbose = fileConfig.verbose ?? 0;
|
|
40
|
+
this.providers = {
|
|
41
|
+
openai: {
|
|
42
|
+
apiKey: fileConfig.providers?.openai?.apiKey ?? "",
|
|
43
|
+
bigModel: fileConfig.providers?.openai?.bigModel ?? "gpt-5.3",
|
|
44
|
+
smallModel: fileConfig.providers?.openai?.smallModel ?? "gpt-5",
|
|
45
|
+
},
|
|
46
|
+
gemini: {
|
|
47
|
+
apiKey: fileConfig.providers?.gemini?.apiKey ?? "",
|
|
48
|
+
bigModel: fileConfig.providers?.gemini?.bigModel ?? "gemini-3.1-pro",
|
|
49
|
+
smallModel: fileConfig.providers?.gemini?.smallModel ?? "gemini-3.1-flash",
|
|
50
|
+
},
|
|
51
|
+
ollama: {
|
|
52
|
+
apiBase: fileConfig.providers?.ollama?.apiBase ?? "http://localhost:11434",
|
|
53
|
+
bigModel: fileConfig.providers?.ollama?.bigModel ?? "llama3.2:3b",
|
|
54
|
+
smallModel: fileConfig.providers?.ollama?.smallModel ?? "llama3.2:3b",
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
if (isNewConfig) {
|
|
58
|
+
this.save({});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
get bigModel() { return this.providers[this.preferredProvider].bigModel; }
|
|
62
|
+
get smallModel() { return this.providers[this.preferredProvider].smallModel; }
|
|
63
|
+
get openaiApiKey() { return this.providers.openai.apiKey; }
|
|
64
|
+
get geminiApiKey() { return this.providers.gemini.apiKey; }
|
|
65
|
+
get ollamaApiBase() { return this.providers.ollama.apiBase; }
|
|
66
|
+
loadFromFile() {
|
|
67
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
68
|
+
try {
|
|
69
|
+
const content = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
70
|
+
return content ? JSON.parse(content) : {};
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
console.error("Failed to parse config file:", e);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
78
|
+
save(updates) {
|
|
79
|
+
try {
|
|
80
|
+
if (updates.preferredProvider)
|
|
81
|
+
this.preferredProvider = updates.preferredProvider;
|
|
82
|
+
if (updates.port)
|
|
83
|
+
this.port = updates.port;
|
|
84
|
+
if (updates.verbose !== undefined)
|
|
85
|
+
this.verbose = updates.verbose;
|
|
86
|
+
if (updates.providers) {
|
|
87
|
+
for (const p in updates.providers) {
|
|
88
|
+
const prov = p;
|
|
89
|
+
this.providers[prov] = {
|
|
90
|
+
...this.providers[prov],
|
|
91
|
+
...updates.providers[prov]
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const fullConfig = {
|
|
96
|
+
preferredProvider: this.preferredProvider,
|
|
97
|
+
port: this.port,
|
|
98
|
+
verbose: this.verbose,
|
|
99
|
+
providers: this.providers
|
|
100
|
+
};
|
|
101
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
102
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
103
|
+
}
|
|
104
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(fullConfig, null, 2));
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
console.error("Failed to save config file:", e);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
isOpenAIModel(model) {
|
|
111
|
+
return this.openaiModels.has(model);
|
|
112
|
+
}
|
|
113
|
+
isGeminiModel(model) {
|
|
114
|
+
return this.geminiModels.has(model);
|
|
115
|
+
}
|
|
116
|
+
isOllamaModel(model) {
|
|
117
|
+
return this.ollamaModels.has(model);
|
|
118
|
+
}
|
|
119
|
+
resolveProvider(model) {
|
|
120
|
+
if (this.isOpenAIModel(model))
|
|
121
|
+
return "openai";
|
|
122
|
+
if (this.isGeminiModel(model))
|
|
123
|
+
return "gemini";
|
|
124
|
+
if (this.isOllamaModel(model))
|
|
125
|
+
return "ollama";
|
|
126
|
+
return this.preferredProvider;
|
|
127
|
+
}
|
|
128
|
+
summary() {
|
|
129
|
+
return {
|
|
130
|
+
preferredProvider: this.preferredProvider,
|
|
131
|
+
port: this.port,
|
|
132
|
+
verbose: this.verbose,
|
|
133
|
+
providers: this.providers
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
export const config = new Config();
|
|
138
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare function convertNonStreaming(openAIResponse: Record<string, any>, claudeModel: string): {
|
|
2
|
+
id: any;
|
|
3
|
+
type: string;
|
|
4
|
+
role: string;
|
|
5
|
+
content: {
|
|
6
|
+
type: string;
|
|
7
|
+
text?: string;
|
|
8
|
+
id?: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
input?: Record<string, unknown>;
|
|
11
|
+
}[];
|
|
12
|
+
model: string;
|
|
13
|
+
stop_reason: string;
|
|
14
|
+
stop_sequence: null;
|
|
15
|
+
usage: {
|
|
16
|
+
input_tokens: any;
|
|
17
|
+
output_tokens: any;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export declare function convertStream(stream: AsyncIterable<string>, claudeModel: string, msgId: string): AsyncGenerator<string>;
|
|
21
|
+
//# sourceMappingURL=converter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../src/converter.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,WAAW,EAAE,MAAM;;;;;cAK7D,MAAM;eAAS,MAAM;aAAO,MAAM;eAAS,MAAM;gBAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;EAwChH;AAcD,wBAAuB,aAAa,CAClC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,EAC7B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GACZ,cAAc,CAAC,MAAM,CAAC,CAoHxB"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
export function convertNonStreaming(openAIResponse, claudeModel) {
|
|
2
|
+
const choice = openAIResponse.choices?.[0];
|
|
3
|
+
if (!choice)
|
|
4
|
+
throw new Error("No choices in response");
|
|
5
|
+
const msg = choice.message;
|
|
6
|
+
const content = [];
|
|
7
|
+
if (msg.content) {
|
|
8
|
+
content.push({ type: "text", text: msg.content });
|
|
9
|
+
}
|
|
10
|
+
if (msg.tool_calls?.length) {
|
|
11
|
+
for (const tc of msg.tool_calls) {
|
|
12
|
+
let parsedInput = {};
|
|
13
|
+
try {
|
|
14
|
+
parsedInput = JSON.parse(tc.function.arguments || "{}");
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// IMP: Provider returned malformed tool-call JSON, falling back to empty input
|
|
18
|
+
parsedInput = {};
|
|
19
|
+
}
|
|
20
|
+
content.push({
|
|
21
|
+
type: "tool_use",
|
|
22
|
+
id: tc.id,
|
|
23
|
+
name: tc.function.name,
|
|
24
|
+
input: parsedInput,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const stopReason = mapStopReason(choice.finish_reason);
|
|
29
|
+
const usage = openAIResponse.usage;
|
|
30
|
+
return {
|
|
31
|
+
id: openAIResponse.id ?? `msg_${Date.now()}`,
|
|
32
|
+
type: "message",
|
|
33
|
+
role: "assistant",
|
|
34
|
+
content,
|
|
35
|
+
model: claudeModel,
|
|
36
|
+
stop_reason: stopReason,
|
|
37
|
+
stop_sequence: null,
|
|
38
|
+
usage: {
|
|
39
|
+
input_tokens: usage?.prompt_tokens ?? 0,
|
|
40
|
+
output_tokens: usage?.completion_tokens ?? 0,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function mapStopReason(finishReason) {
|
|
45
|
+
switch (finishReason) {
|
|
46
|
+
case "stop": return "end_turn";
|
|
47
|
+
case "length": return "max_tokens";
|
|
48
|
+
case "tool_calls": return "tool_use";
|
|
49
|
+
case "content_filter": return "end_turn";
|
|
50
|
+
default: return "end_turn";
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// ─── Streaming ────────────────────────────────────────────────────────────────
|
|
54
|
+
export async function* convertStream(stream, claudeModel, msgId) {
|
|
55
|
+
const id = msgId || `msg_${Date.now()}`;
|
|
56
|
+
// message_start
|
|
57
|
+
yield `event: message_start\ndata: ${JSON.stringify({
|
|
58
|
+
type: "message_start",
|
|
59
|
+
message: {
|
|
60
|
+
id,
|
|
61
|
+
type: "message",
|
|
62
|
+
role: "assistant",
|
|
63
|
+
content: [],
|
|
64
|
+
model: claudeModel,
|
|
65
|
+
stop_reason: null,
|
|
66
|
+
stop_sequence: null,
|
|
67
|
+
usage: { input_tokens: 0, output_tokens: 0 },
|
|
68
|
+
},
|
|
69
|
+
})}\n\n`;
|
|
70
|
+
let blockIndex = 0;
|
|
71
|
+
let currentBlockType = null;
|
|
72
|
+
let toolCallAccumulators = {};
|
|
73
|
+
let inputTokens = 0;
|
|
74
|
+
let outputTokens = 0;
|
|
75
|
+
for await (const line of stream) {
|
|
76
|
+
if (!line.startsWith("data: "))
|
|
77
|
+
continue;
|
|
78
|
+
const data = line.slice(6).trim();
|
|
79
|
+
if (data === "[DONE]")
|
|
80
|
+
break;
|
|
81
|
+
let chunk;
|
|
82
|
+
try {
|
|
83
|
+
chunk = JSON.parse(data);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const choice = chunk.choices?.[0];
|
|
89
|
+
if (!choice)
|
|
90
|
+
continue;
|
|
91
|
+
const delta = choice.delta;
|
|
92
|
+
// Track usage if present
|
|
93
|
+
if (chunk.usage) {
|
|
94
|
+
inputTokens = chunk.usage.prompt_tokens ?? inputTokens;
|
|
95
|
+
outputTokens = chunk.usage.completion_tokens ?? outputTokens;
|
|
96
|
+
}
|
|
97
|
+
// Text delta
|
|
98
|
+
if (delta?.content !== undefined && delta.content !== null) {
|
|
99
|
+
if (currentBlockType !== "text") {
|
|
100
|
+
if (currentBlockType !== null) {
|
|
101
|
+
yield `event: content_block_stop\ndata: ${JSON.stringify({ type: "content_block_stop", index: blockIndex })}\n\n`;
|
|
102
|
+
blockIndex++;
|
|
103
|
+
}
|
|
104
|
+
currentBlockType = "text";
|
|
105
|
+
yield `event: content_block_start\ndata: ${JSON.stringify({
|
|
106
|
+
type: "content_block_start",
|
|
107
|
+
index: blockIndex,
|
|
108
|
+
content_block: { type: "text", text: "" },
|
|
109
|
+
})}\n\n`;
|
|
110
|
+
}
|
|
111
|
+
yield `event: content_block_delta\ndata: ${JSON.stringify({
|
|
112
|
+
type: "content_block_delta",
|
|
113
|
+
index: blockIndex,
|
|
114
|
+
delta: { type: "text_delta", text: delta.content },
|
|
115
|
+
})}\n\n`;
|
|
116
|
+
}
|
|
117
|
+
// Tool call deltas
|
|
118
|
+
if (delta?.tool_calls?.length) {
|
|
119
|
+
for (const tc of delta.tool_calls) {
|
|
120
|
+
const tcIdx = tc.index ?? 0;
|
|
121
|
+
if (!toolCallAccumulators[tcIdx]) {
|
|
122
|
+
// New tool call block
|
|
123
|
+
if (currentBlockType !== null) {
|
|
124
|
+
yield `event: content_block_stop\ndata: ${JSON.stringify({ type: "content_block_stop", index: blockIndex })}\n\n`;
|
|
125
|
+
blockIndex++;
|
|
126
|
+
}
|
|
127
|
+
toolCallAccumulators[tcIdx] = { id: tc.id ?? "", name: tc.function?.name ?? "", args: "" };
|
|
128
|
+
currentBlockType = "tool_use";
|
|
129
|
+
yield `event: content_block_start\ndata: ${JSON.stringify({
|
|
130
|
+
type: "content_block_start",
|
|
131
|
+
index: blockIndex,
|
|
132
|
+
content_block: { type: "tool_use", id: tc.id, name: tc.function?.name, input: {} },
|
|
133
|
+
})}\n\n`;
|
|
134
|
+
}
|
|
135
|
+
if (tc.function?.arguments) {
|
|
136
|
+
toolCallAccumulators[tcIdx].args += tc.function.arguments;
|
|
137
|
+
yield `event: content_block_delta\ndata: ${JSON.stringify({
|
|
138
|
+
type: "content_block_delta",
|
|
139
|
+
index: blockIndex,
|
|
140
|
+
delta: { type: "input_json_delta", partial_json: tc.function.arguments },
|
|
141
|
+
})}\n\n`;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Finish
|
|
146
|
+
if (choice.finish_reason) {
|
|
147
|
+
if (currentBlockType !== null) {
|
|
148
|
+
yield `event: content_block_stop\ndata: ${JSON.stringify({ type: "content_block_stop", index: blockIndex })}\n\n`;
|
|
149
|
+
}
|
|
150
|
+
yield `event: message_delta\ndata: ${JSON.stringify({
|
|
151
|
+
type: "message_delta",
|
|
152
|
+
delta: { stop_reason: mapStopReason(choice.finish_reason), stop_sequence: null },
|
|
153
|
+
usage: { output_tokens: outputTokens },
|
|
154
|
+
})}\n\n`;
|
|
155
|
+
yield `event: message_stop\ndata: ${JSON.stringify({ type: "message_stop" })}\n\n`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=converter.js.map
|