@himanshu806/ccproxy 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.
Files changed (47) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +33 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +202 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/config.d.ts +43 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +138 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/converter.d.ts +21 -0
  12. package/dist/converter.d.ts.map +1 -0
  13. package/dist/converter.js +159 -0
  14. package/dist/converter.js.map +1 -0
  15. package/dist/logger.d.ts +5 -0
  16. package/dist/logger.d.ts.map +1 -0
  17. package/dist/logger.js +73 -0
  18. package/dist/logger.js.map +1 -0
  19. package/dist/providers/gemini.d.ts +22 -0
  20. package/dist/providers/gemini.d.ts.map +1 -0
  21. package/dist/providers/gemini.js +45 -0
  22. package/dist/providers/gemini.js.map +1 -0
  23. package/dist/providers/index.d.ts +4 -0
  24. package/dist/providers/index.d.ts.map +1 -0
  25. package/dist/providers/index.js +4 -0
  26. package/dist/providers/index.js.map +1 -0
  27. package/dist/providers/ollama.d.ts +22 -0
  28. package/dist/providers/ollama.d.ts.map +1 -0
  29. package/dist/providers/ollama.js +44 -0
  30. package/dist/providers/ollama.js.map +1 -0
  31. package/dist/providers/openai.d.ts +22 -0
  32. package/dist/providers/openai.d.ts.map +1 -0
  33. package/dist/providers/openai.js +38 -0
  34. package/dist/providers/openai.js.map +1 -0
  35. package/dist/server.d.ts +3 -0
  36. package/dist/server.d.ts.map +1 -0
  37. package/dist/server.js +73 -0
  38. package/dist/server.js.map +1 -0
  39. package/dist/translator.d.ts +3 -0
  40. package/dist/translator.d.ts.map +1 -0
  41. package/dist/translator.js +155 -0
  42. package/dist/translator.js.map +1 -0
  43. package/dist/types.d.ts +108 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +3 -0
  46. package/dist/types.js.map +1 -0
  47. 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,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -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