@andyzheung/ccmr 1.2.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/dist/config.js ADDED
@@ -0,0 +1,292 @@
1
+ "use strict";
2
+ /**
3
+ * Configuration management for Claude Code Model Router
4
+ */
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.ConfigManager = void 0;
10
+ exports.generateConfigFile = generateConfigFile;
11
+ exports.generateEnvFile = generateEnvFile;
12
+ const node_fs_1 = __importDefault(require("node:fs"));
13
+ const node_path_1 = __importDefault(require("node:path"));
14
+ const js_yaml_1 = __importDefault(require("js-yaml"));
15
+ const dotenv_1 = require("dotenv");
16
+ // Load .env file
17
+ (0, dotenv_1.config)();
18
+ const DEFAULT_CONFIG = {
19
+ default_model: 'deepseek',
20
+ models: {
21
+ deepseek: {
22
+ display_name: 'DeepSeek V3.2',
23
+ provider: 'deepseek',
24
+ model_id: 'deepseek-chat',
25
+ base_url: 'https://api.deepseek.com/anthropic',
26
+ api_key_env: 'DEEPSEEK_API_KEY',
27
+ auth_header: 'x-api-key',
28
+ supports_streaming: true,
29
+ supports_tools: true,
30
+ max_tokens: 128000,
31
+ context_window: 128000,
32
+ },
33
+ kimi: {
34
+ display_name: 'Kimi K2 Thinking',
35
+ provider: 'moonshot',
36
+ model_id: 'kimi-for-coding',
37
+ base_url: 'https://api.kimi.com/coding/',
38
+ api_key_env: 'KIMI_API_KEY',
39
+ auth_header: 'x-api-key',
40
+ supports_streaming: true,
41
+ supports_tools: true,
42
+ max_tokens: 32768,
43
+ context_window: 256000,
44
+ },
45
+ minimax: {
46
+ display_name: 'MiniMax M2.5',
47
+ provider: 'minimax',
48
+ model_id: 'MiniMax-M2.5',
49
+ base_url: 'https://api.minimaxi.com/anthropic',
50
+ api_key_env: 'MINIMAX_API_KEY',
51
+ auth_header: 'x-api-key',
52
+ supports_streaming: true,
53
+ supports_tools: true,
54
+ max_tokens: 128000,
55
+ context_window: 200000,
56
+ },
57
+ qwen: {
58
+ display_name: 'Qwen3 Max',
59
+ provider: 'alibaba',
60
+ model_id: 'qwen-plus',
61
+ base_url: 'https://dashscope.aliyuncs.com/apps/anthropic',
62
+ api_key_env: 'QWEN_API_KEY',
63
+ auth_header: 'x-api-key',
64
+ supports_streaming: true,
65
+ supports_tools: true,
66
+ max_tokens: 32768,
67
+ context_window: 256000,
68
+ },
69
+ glm: {
70
+ display_name: 'GLM 5.0',
71
+ provider: 'zhipu',
72
+ model_id: 'glm-5',
73
+ base_url: 'https://open.bigmodel.cn/api/anthropic',
74
+ api_key_env: 'GLM_API_KEY',
75
+ auth_header: 'x-api-key',
76
+ supports_streaming: true,
77
+ supports_tools: true,
78
+ max_tokens: 128000,
79
+ context_window: 200000,
80
+ },
81
+ },
82
+ aliases: {
83
+ 'deepseek-v3': 'deepseek',
84
+ 'deepseek-chat': 'deepseek',
85
+ 'ds': 'deepseek',
86
+ 'kimi-k2': 'kimi',
87
+ 'kimi-k2-thinking': 'kimi',
88
+ 'moonshot': 'kimi',
89
+ 'minimax-m2': 'minimax',
90
+ 'minimax-m2.1': 'minimax',
91
+ 'minimax-m2.5': 'minimax',
92
+ 'mm': 'minimax',
93
+ 'qwen3': 'qwen',
94
+ 'qwen3-max': 'qwen',
95
+ 'tongyi': 'qwen',
96
+ 'glm-4.7': 'glm',
97
+ 'glm-4.6': 'glm',
98
+ 'glm-5': 'glm',
99
+ 'glm-5.0': 'glm',
100
+ 'zhipu': 'glm',
101
+ 'chatglm': 'glm',
102
+ },
103
+ gateway: {
104
+ host: '0.0.0.0',
105
+ port: 8080,
106
+ timeout: 300,
107
+ enable_logging: true,
108
+ log_level: 'INFO',
109
+ },
110
+ };
111
+ class ConfigManager {
112
+ config;
113
+ apiKeys = new Map();
114
+ constructor(configPath) {
115
+ this.config = this.loadConfig(configPath);
116
+ this.loadApiKeys();
117
+ }
118
+ loadConfig(configPath) {
119
+ // Try to find config file
120
+ const possiblePaths = [
121
+ configPath,
122
+ node_path_1.default.join(process.cwd(), 'models.yaml'),
123
+ node_path_1.default.join(process.cwd(), 'config', 'models.yaml'),
124
+ node_path_1.default.join(process.cwd(), '.ccmr-plus.yaml'),
125
+ ].filter(Boolean);
126
+ for (const p of possiblePaths) {
127
+ if (node_fs_1.default.existsSync(p)) {
128
+ try {
129
+ const content = node_fs_1.default.readFileSync(p, 'utf-8');
130
+ const parsed = js_yaml_1.default.load(content);
131
+ return this.mergeConfig(parsed);
132
+ }
133
+ catch (e) {
134
+ console.warn(`Warning: Failed to parse config file ${p}:`, e);
135
+ }
136
+ }
137
+ }
138
+ // Return default config if no file found
139
+ return DEFAULT_CONFIG;
140
+ }
141
+ mergeConfig(parsed) {
142
+ return {
143
+ default_model: parsed.default_model ?? DEFAULT_CONFIG.default_model,
144
+ models: { ...DEFAULT_CONFIG.models, ...parsed.models },
145
+ aliases: { ...DEFAULT_CONFIG.aliases, ...parsed.aliases },
146
+ gateway: { ...DEFAULT_CONFIG.gateway, ...parsed.gateway },
147
+ };
148
+ }
149
+ loadApiKeys() {
150
+ for (const [name, model] of Object.entries(this.config.models)) {
151
+ const key = process.env[model.api_key_env];
152
+ if (key) {
153
+ this.apiKeys.set(name, key);
154
+ }
155
+ }
156
+ }
157
+ getConfig() {
158
+ return this.config;
159
+ }
160
+ getModel(name) {
161
+ // Check direct model name
162
+ if (this.config.models[name]) {
163
+ return this.config.models[name];
164
+ }
165
+ // Check aliases
166
+ const aliasTarget = this.config.aliases[name];
167
+ if (aliasTarget && this.config.models[aliasTarget]) {
168
+ return this.config.models[aliasTarget];
169
+ }
170
+ return undefined;
171
+ }
172
+ resolveModelName(name) {
173
+ if (this.config.aliases[name]) {
174
+ return this.config.aliases[name];
175
+ }
176
+ if (this.config.models[name]) {
177
+ return name;
178
+ }
179
+ return name;
180
+ }
181
+ getApiKey(modelName) {
182
+ const resolved = this.resolveModelName(modelName);
183
+ return this.apiKeys.get(resolved);
184
+ }
185
+ listModels() {
186
+ const result = {};
187
+ for (const [name, model] of Object.entries(this.config.models)) {
188
+ result[name] = {
189
+ displayName: model.display_name,
190
+ provider: model.provider,
191
+ available: this.apiKeys.has(name),
192
+ };
193
+ }
194
+ return result;
195
+ }
196
+ }
197
+ exports.ConfigManager = ConfigManager;
198
+ // Generate default config file content
199
+ function generateConfigFile() {
200
+ return `# CCMR-Plus Configuration
201
+ # Place this file as models.yaml or .ccmr-plus.yaml in your project root
202
+
203
+ default_model: deepseek
204
+
205
+ models:
206
+ deepseek:
207
+ display_name: "DeepSeek V3.2"
208
+ provider: deepseek
209
+ model_id: deepseek-chat
210
+ base_url: https://api.deepseek.com/anthropic
211
+ api_key_env: DEEPSEEK_API_KEY
212
+ auth_header: x-api-key
213
+ max_tokens: 128000
214
+ context_window: 128000
215
+
216
+ kimi:
217
+ display_name: "Kimi K2 Thinking"
218
+ provider: moonshot
219
+ model_id: kimi-for-coding
220
+ base_url: https://api.kimi.com/coding/
221
+ api_key_env: KIMI_API_KEY
222
+ auth_header: x-api-key
223
+ max_tokens: 32768
224
+ context_window: 256000
225
+
226
+ minimax:
227
+ display_name: "MiniMax M2.5"
228
+ provider: minimax
229
+ model_id: MiniMax-M2.5
230
+ base_url: https://api.minimaxi.com/anthropic
231
+ api_key_env: MINIMAX_API_KEY
232
+ auth_header: x-api-key
233
+ max_tokens: 128000
234
+ context_window: 200000
235
+
236
+ qwen:
237
+ display_name: "Qwen3 Max"
238
+ provider: alibaba
239
+ model_id: qwen-plus
240
+ base_url: https://dashscope.aliyuncs.com/apps/anthropic
241
+ api_key_env: QWEN_API_KEY
242
+ auth_header: x-api-key
243
+ max_tokens: 32768
244
+ context_window: 256000
245
+
246
+ glm:
247
+ display_name: "GLM 5.0"
248
+ provider: zhipu
249
+ model_id: glm-5
250
+ base_url: https://open.bigmodel.cn/api/anthropic
251
+ api_key_env: GLM_API_KEY
252
+ auth_header: x-api-key
253
+ max_tokens: 128000
254
+ context_window: 200000
255
+
256
+ aliases:
257
+ ds: deepseek
258
+ deepseek-v3.2: deepseek
259
+ mm: minimax
260
+ minimax-m2.1: minimax
261
+ minimax-m2.5: minimax
262
+ kimi-k2: kimi
263
+ qwen3-max: qwen
264
+ glm-4.7: glm
265
+ glm-5: glm
266
+
267
+ gateway:
268
+ port: 8080
269
+ timeout: 300
270
+ `;
271
+ }
272
+ function generateEnvFile() {
273
+ return `# Claude Code Model Router - API Keys
274
+ # Fill in your API keys below
275
+
276
+ # DeepSeek - https://platform.deepseek.com/
277
+ DEEPSEEK_API_KEY=
278
+
279
+ # Kimi - https://www.kimi.com/
280
+ KIMI_API_KEY=
281
+
282
+ # MiniMax - https://platform.minimax.io/
283
+ MINIMAX_API_KEY=
284
+
285
+ # Qwen - https://dashscope.console.aliyun.com/
286
+ QWEN_API_KEY=
287
+
288
+ # GLM - https://open.bigmodel.cn/
289
+ GLM_API_KEY=
290
+ `;
291
+ }
292
+ //# 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,12 @@
1
+ /**
2
+ * Claude Code Model Router
3
+ *
4
+ * A lightweight API gateway for routing Claude Code requests to multiple AI models.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ export { ConfigManager, generateConfigFile, generateEnvFile } from './config.js';
9
+ export { ModelRouter, RouterError } from './router.js';
10
+ export { createServer, startServer } from './server.js';
11
+ export type { ModelConfig, GatewayConfig, RouterConfig, MessagesRequest, MessagesResponse, ErrorResponse, Message, ContentBlock, Tool, Usage, RouteInfo, } from './types.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EACV,WAAW,EACX,aAAa,EACb,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,OAAO,EACP,YAAY,EACZ,IAAI,EACJ,KAAK,EACL,SAAS,GACV,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /**
3
+ * Claude Code Model Router
4
+ *
5
+ * A lightweight API gateway for routing Claude Code requests to multiple AI models.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.startServer = exports.createServer = exports.RouterError = exports.ModelRouter = exports.generateEnvFile = exports.generateConfigFile = exports.ConfigManager = void 0;
11
+ var config_js_1 = require("./config.js");
12
+ Object.defineProperty(exports, "ConfigManager", { enumerable: true, get: function () { return config_js_1.ConfigManager; } });
13
+ Object.defineProperty(exports, "generateConfigFile", { enumerable: true, get: function () { return config_js_1.generateConfigFile; } });
14
+ Object.defineProperty(exports, "generateEnvFile", { enumerable: true, get: function () { return config_js_1.generateEnvFile; } });
15
+ var router_js_1 = require("./router.js");
16
+ Object.defineProperty(exports, "ModelRouter", { enumerable: true, get: function () { return router_js_1.ModelRouter; } });
17
+ Object.defineProperty(exports, "RouterError", { enumerable: true, get: function () { return router_js_1.RouterError; } });
18
+ var server_js_1 = require("./server.js");
19
+ Object.defineProperty(exports, "createServer", { enumerable: true, get: function () { return server_js_1.createServer; } });
20
+ Object.defineProperty(exports, "startServer", { enumerable: true, get: function () { return server_js_1.startServer; } });
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,yCAAiF;AAAxE,0GAAA,aAAa,OAAA;AAAE,+GAAA,kBAAkB,OAAA;AAAE,4GAAA,eAAe,OAAA;AAC3D,yCAAuD;AAA9C,wGAAA,WAAW,OAAA;AAAE,wGAAA,WAAW,OAAA;AACjC,yCAAwD;AAA/C,yGAAA,YAAY,OAAA;AAAE,wGAAA,WAAW,OAAA"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Request routing and forwarding logic
3
+ */
4
+ import type { ConfigManager } from './config.js';
5
+ import type { MessagesRequest, MessagesResponse, ErrorResponse, ModelConfig, RouteInfo } from './types.js';
6
+ export declare class RouterError extends Error {
7
+ statusCode: number;
8
+ errorType: string;
9
+ constructor(message: string, statusCode?: number, errorType?: string);
10
+ toErrorResponse(): ErrorResponse;
11
+ }
12
+ export declare class ModelRouter {
13
+ private configManager;
14
+ constructor(configManager: ConfigManager);
15
+ resolveRoute(modelName: string): RouteInfo;
16
+ buildHeaders(route: RouteInfo, originalHeaders: Record<string, string>): Record<string, string>;
17
+ buildRequestBody(request: MessagesRequest, modelConfig: ModelConfig): Record<string, unknown>;
18
+ buildUrl(modelConfig: ModelConfig, endpoint?: string): string;
19
+ forwardRequest(request: MessagesRequest, originalHeaders: Record<string, string>): Promise<MessagesResponse>;
20
+ forwardStream(request: MessagesRequest, originalHeaders: Record<string, string>): AsyncGenerator<string>;
21
+ }
22
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,qBAAa,WAAY,SAAQ,KAAK;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;gBAEN,OAAO,EAAE,MAAM,EAAE,UAAU,SAAM,EAAE,SAAS,SAAiB;IAOzE,eAAe,IAAI,aAAa;CASjC;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,aAAa,CAAgB;gBAEzB,aAAa,EAAE,aAAa;IAIxC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;IA8B1C,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAkB/F,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAe7F,QAAQ,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,SAAiB,GAAG,MAAM;IAoB/D,cAAc,CAClB,OAAO,EAAE,eAAe,EACxB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,OAAO,CAAC,gBAAgB,CAAC;IA6ErB,aAAa,CAClB,OAAO,EAAE,eAAe,EACxB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,cAAc,CAAC,MAAM,CAAC;CAuG1B"}
package/dist/router.js ADDED
@@ -0,0 +1,234 @@
1
+ "use strict";
2
+ /**
3
+ * Request routing and forwarding logic
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ModelRouter = exports.RouterError = void 0;
7
+ class RouterError extends Error {
8
+ statusCode;
9
+ errorType;
10
+ constructor(message, statusCode = 500, errorType = 'router_error') {
11
+ super(message);
12
+ this.name = 'RouterError';
13
+ this.statusCode = statusCode;
14
+ this.errorType = errorType;
15
+ }
16
+ toErrorResponse() {
17
+ return {
18
+ type: 'error',
19
+ error: {
20
+ type: this.errorType,
21
+ message: this.message,
22
+ },
23
+ };
24
+ }
25
+ }
26
+ exports.RouterError = RouterError;
27
+ class ModelRouter {
28
+ configManager;
29
+ constructor(configManager) {
30
+ this.configManager = configManager;
31
+ }
32
+ resolveRoute(modelName) {
33
+ const resolvedName = this.configManager.resolveModelName(modelName);
34
+ const modelConfig = this.configManager.getModel(resolvedName);
35
+ if (!modelConfig) {
36
+ const availableModels = Object.keys(this.configManager.getConfig().models).join(', ');
37
+ throw new RouterError(`Model '${modelName}' not found. Available models: ${availableModels}`, 400, 'invalid_model');
38
+ }
39
+ const apiKey = this.configManager.getApiKey(resolvedName);
40
+ if (!apiKey) {
41
+ throw new RouterError(`API key not configured for model '${modelConfig.display_name}'. ` +
42
+ `Please set the ${modelConfig.api_key_env} environment variable.`, 401, 'authentication_error');
43
+ }
44
+ return {
45
+ name: resolvedName,
46
+ config: modelConfig,
47
+ apiKey,
48
+ };
49
+ }
50
+ buildHeaders(route, originalHeaders) {
51
+ const headers = {
52
+ 'Content-Type': 'application/json',
53
+ Accept: 'application/json',
54
+ [route.config.auth_header || 'x-api-key']: route.apiKey,
55
+ };
56
+ // Add Anthropic-specific headers for Anthropic provider
57
+ if (route.config.provider === 'anthropic') {
58
+ headers['anthropic-version'] = '2023-06-01';
59
+ if (originalHeaders['anthropic-beta']) {
60
+ headers['anthropic-beta'] = originalHeaders['anthropic-beta'];
61
+ }
62
+ }
63
+ return headers;
64
+ }
65
+ buildRequestBody(request, modelConfig) {
66
+ const body = { ...request };
67
+ // Replace model name with actual model ID
68
+ body.model = modelConfig.model_id;
69
+ // Cap max_tokens if exceeds model limit
70
+ const maxTokens = modelConfig.max_tokens || 8192;
71
+ if (body.max_tokens && body.max_tokens > maxTokens) {
72
+ body.max_tokens = maxTokens;
73
+ }
74
+ return body;
75
+ }
76
+ buildUrl(modelConfig, endpoint = '/v1/messages') {
77
+ let baseUrl = modelConfig.base_url.replace(/\/$/, '');
78
+ // Handle different API structures
79
+ if (modelConfig.provider === 'anthropic') {
80
+ return `${baseUrl}${endpoint}`;
81
+ }
82
+ // For other providers with /anthropic or /coding in base URL
83
+ if (baseUrl.includes('/anthropic') ||
84
+ baseUrl.includes('/coding') ||
85
+ baseUrl.includes('/apps/anthropic')) {
86
+ return `${baseUrl}/v1/messages`;
87
+ }
88
+ return `${baseUrl}${endpoint}`;
89
+ }
90
+ async forwardRequest(request, originalHeaders) {
91
+ const route = this.resolveRoute(request.model);
92
+ const headers = this.buildHeaders(route, originalHeaders);
93
+ const body = this.buildRequestBody(request, route.config);
94
+ const url = this.buildUrl(route.config);
95
+ // Ensure stream is false for non-streaming
96
+ body.stream = false;
97
+ const timeout = this.configManager.getConfig().gateway.timeout * 1000;
98
+ const controller = new AbortController();
99
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
100
+ try {
101
+ const response = await fetch(url, {
102
+ method: 'POST',
103
+ headers,
104
+ body: JSON.stringify(body),
105
+ signal: controller.signal,
106
+ });
107
+ clearTimeout(timeoutId);
108
+ if (!response.ok) {
109
+ const errorText = await response.text();
110
+ let errorMessage = errorText;
111
+ try {
112
+ const errorJson = JSON.parse(errorText);
113
+ errorMessage = errorJson.error?.message || errorText;
114
+ }
115
+ catch {
116
+ // Use raw text
117
+ }
118
+ throw new RouterError(`Upstream API error (${route.config.provider}): ${errorMessage}`, response.status, 'api_error');
119
+ }
120
+ const data = (await response.json());
121
+ if (this.configManager.getConfig().gateway.enable_logging) {
122
+ console.log(`[${route.config.display_name}] Request completed | ` +
123
+ `Input: ${data.usage?.input_tokens ?? 'N/A'} | ` +
124
+ `Output: ${data.usage?.output_tokens ?? 'N/A'}`);
125
+ }
126
+ return data;
127
+ }
128
+ catch (error) {
129
+ clearTimeout(timeoutId);
130
+ if (error instanceof RouterError) {
131
+ throw error;
132
+ }
133
+ if (error instanceof Error) {
134
+ if (error.name === 'AbortError') {
135
+ throw new RouterError(`Request timed out after ${timeout / 1000}s`, 504, 'timeout_error');
136
+ }
137
+ throw new RouterError(`Connection error: ${error.message}`, 502, 'connection_error');
138
+ }
139
+ throw new RouterError('Unknown error occurred', 500, 'internal_error');
140
+ }
141
+ }
142
+ async *forwardStream(request, originalHeaders) {
143
+ const route = this.resolveRoute(request.model);
144
+ const headers = this.buildHeaders(route, originalHeaders);
145
+ const body = this.buildRequestBody(request, route.config);
146
+ const url = this.buildUrl(route.config);
147
+ // Ensure stream is true
148
+ body.stream = true;
149
+ headers.Accept = 'text/event-stream';
150
+ const timeout = this.configManager.getConfig().gateway.timeout * 1000;
151
+ const controller = new AbortController();
152
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
153
+ try {
154
+ const response = await fetch(url, {
155
+ method: 'POST',
156
+ headers,
157
+ body: JSON.stringify(body),
158
+ signal: controller.signal,
159
+ });
160
+ clearTimeout(timeoutId);
161
+ if (!response.ok) {
162
+ const errorText = await response.text();
163
+ let errorMessage = errorText;
164
+ try {
165
+ const errorJson = JSON.parse(errorText);
166
+ errorMessage = errorJson.error?.message || errorText;
167
+ }
168
+ catch {
169
+ // Use raw text
170
+ }
171
+ const errorEvent = {
172
+ type: 'error',
173
+ error: { type: 'api_error', message: errorMessage },
174
+ };
175
+ yield `event: error\ndata: ${JSON.stringify(errorEvent)}\n\n`;
176
+ return;
177
+ }
178
+ if (!response.body) {
179
+ throw new RouterError('No response body', 500, 'internal_error');
180
+ }
181
+ const reader = response.body.getReader();
182
+ const decoder = new TextDecoder();
183
+ let buffer = '';
184
+ let eventCount = 0;
185
+ while (true) {
186
+ const { done, value } = await reader.read();
187
+ if (done)
188
+ break;
189
+ const chunk = decoder.decode(value, { stream: true });
190
+ buffer += chunk;
191
+ // Process complete SSE events
192
+ while (buffer.includes('\n\n')) {
193
+ const idx = buffer.indexOf('\n\n');
194
+ const event = buffer.slice(0, idx);
195
+ buffer = buffer.slice(idx + 2);
196
+ if (event.trim()) {
197
+ eventCount++;
198
+ yield event + '\n\n';
199
+ }
200
+ }
201
+ }
202
+ // Don't forget remaining data
203
+ if (buffer.trim()) {
204
+ eventCount++;
205
+ yield buffer + '\n\n';
206
+ }
207
+ console.log(`[${route.config.display_name}] Yielded ${eventCount} events`);
208
+ if (this.configManager.getConfig().gateway.enable_logging) {
209
+ console.log(`[${route.config.display_name}] Stream completed`);
210
+ }
211
+ }
212
+ catch (error) {
213
+ clearTimeout(timeoutId);
214
+ let errorMessage = 'Unknown error';
215
+ let errorType = 'internal_error';
216
+ if (error instanceof Error) {
217
+ if (error.name === 'AbortError') {
218
+ errorMessage = `Request timed out after ${timeout / 1000}s`;
219
+ errorType = 'timeout_error';
220
+ }
221
+ else {
222
+ errorMessage = error.message;
223
+ }
224
+ }
225
+ const errorEvent = {
226
+ type: 'error',
227
+ error: { type: errorType, message: errorMessage },
228
+ };
229
+ yield `event: error\ndata: ${JSON.stringify(errorEvent)}\n\n`;
230
+ }
231
+ }
232
+ }
233
+ exports.ModelRouter = ModelRouter;
234
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Express server for Claude Code Model Router
3
+ */
4
+ import { ConfigManager } from './config.js';
5
+ export declare function createServer(configManager: ConfigManager): import("express-serve-static-core").Express;
6
+ export declare function startServer(configManager: ConfigManager): void;
7
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAI5C,wBAAgB,YAAY,CAAC,aAAa,EAAE,aAAa,+CAmKxD;AAED,wBAAgB,WAAW,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI,CA2B9D"}