cc-hub-cli 1.1.14 → 1.1.16
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/index.js +268 -38
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { Command as Command2 } from "commander";
|
|
|
10
10
|
// src/config.ts
|
|
11
11
|
import fs4 from "fs";
|
|
12
12
|
import path4 from "path";
|
|
13
|
-
import
|
|
13
|
+
import os4 from "os";
|
|
14
14
|
|
|
15
15
|
// src/platform/desktop-app.ts
|
|
16
16
|
import fs2 from "fs";
|
|
@@ -266,16 +266,55 @@ function sanitizeToolId(id) {
|
|
|
266
266
|
}
|
|
267
267
|
return sanitized;
|
|
268
268
|
}
|
|
269
|
+
function buildSystemMessage(system) {
|
|
270
|
+
if (typeof system === "string") {
|
|
271
|
+
return { role: "system", content: system };
|
|
272
|
+
}
|
|
273
|
+
if (Array.isArray(system)) {
|
|
274
|
+
const textBlocks = system.filter((b) => b.type === "text" && b.text);
|
|
275
|
+
const hasCacheControl = textBlocks.some((b) => b.cache_control);
|
|
276
|
+
if (hasCacheControl) {
|
|
277
|
+
const parts = textBlocks.map((b) => {
|
|
278
|
+
const part = { type: "text", text: b.text };
|
|
279
|
+
if (b.cache_control) part.cache_control = b.cache_control;
|
|
280
|
+
return part;
|
|
281
|
+
});
|
|
282
|
+
if (parts.length > 0) return { role: "system", content: parts };
|
|
283
|
+
} else {
|
|
284
|
+
const text = textBlocks.map((b) => b.text).join("\n");
|
|
285
|
+
if (text) return { role: "system", content: text };
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
function convertAnthropicContentPart(part) {
|
|
291
|
+
let convertedPart = null;
|
|
292
|
+
if (part.type === "image") {
|
|
293
|
+
if (part.source?.type === "base64" && part.source.media_type && part.source.data) {
|
|
294
|
+
const url = `data:${part.source.media_type};base64,${part.source.data}`;
|
|
295
|
+
debug(`transform: converting base64 image (${part.source.media_type}, ${part.source.data.length} chars)`);
|
|
296
|
+
convertedPart = { type: "image_url", image_url: { url } };
|
|
297
|
+
} else if (part.source?.type === "url" && part.source.url) {
|
|
298
|
+
debug(`transform: converting image url (${part.source.url.slice(0, 80)}...)`);
|
|
299
|
+
convertedPart = { type: "image_url", image_url: { url: part.source.url } };
|
|
300
|
+
} else {
|
|
301
|
+
warn(`transform: skipping invalid image block (missing source fields)`);
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
} else if (part.type === "text") {
|
|
305
|
+
convertedPart = { type: "text", text: part.text };
|
|
306
|
+
}
|
|
307
|
+
if (convertedPart && part.cache_control) {
|
|
308
|
+
convertedPart.cache_control = part.cache_control;
|
|
309
|
+
}
|
|
310
|
+
return convertedPart;
|
|
311
|
+
}
|
|
269
312
|
function transformAnthropicToOpenAI(body) {
|
|
270
313
|
debug(`transform: anthropic -> openai model=${body.model} messages=${(body.messages ?? []).length}`);
|
|
271
314
|
const messages = [];
|
|
272
315
|
if (body.system) {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
} else if (Array.isArray(body.system)) {
|
|
276
|
-
const text = body.system.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("\n");
|
|
277
|
-
if (text) messages.push({ role: "system", content: text });
|
|
278
|
-
}
|
|
316
|
+
const systemMsg = buildSystemMessage(body.system);
|
|
317
|
+
if (systemMsg) messages.push(systemMsg);
|
|
279
318
|
}
|
|
280
319
|
for (const msg of body.messages ?? []) {
|
|
281
320
|
if (typeof msg.content === "string") {
|
|
@@ -301,23 +340,9 @@ function transformAnthropicToOpenAI(body) {
|
|
|
301
340
|
(b) => b.type === "text" && b.text || b.type === "image" && (b.source?.type === "base64" && b.source.media_type && b.source.data || b.source?.type === "url" && b.source.url)
|
|
302
341
|
);
|
|
303
342
|
if (contentParts.length > 0) {
|
|
304
|
-
const converted = contentParts.map((
|
|
305
|
-
if (part.type === "image") {
|
|
306
|
-
if (part.source?.type === "base64" && part.source.media_type && part.source.data) {
|
|
307
|
-
const url = `data:${part.source.media_type};base64,${part.source.data}`;
|
|
308
|
-
debug(`transform: converting base64 image (${part.source.media_type}, ${part.source.data.length} chars)`);
|
|
309
|
-
return { type: "image_url", image_url: { url } };
|
|
310
|
-
} else if (part.source?.type === "url" && part.source.url) {
|
|
311
|
-
debug(`transform: converting image url (${part.source.url.slice(0, 80)}...)`);
|
|
312
|
-
return { type: "image_url", image_url: { url: part.source.url } };
|
|
313
|
-
}
|
|
314
|
-
warn(`transform: skipping invalid image block (missing source fields)`);
|
|
315
|
-
return null;
|
|
316
|
-
}
|
|
317
|
-
return { type: "text", text: part.text };
|
|
318
|
-
}).filter(Boolean);
|
|
343
|
+
const converted = contentParts.map(convertAnthropicContentPart).filter(Boolean);
|
|
319
344
|
if (converted.length === 0) {
|
|
320
|
-
} else if (converted.every((p) => p.type === "text")) {
|
|
345
|
+
} else if (converted.every((p) => p.type === "text") && !converted.some((p) => p.cache_control)) {
|
|
321
346
|
messages.push({
|
|
322
347
|
role: "user",
|
|
323
348
|
content: converted.map((p) => p.text).join("")
|
|
@@ -334,6 +359,12 @@ function transformAnthropicToOpenAI(body) {
|
|
|
334
359
|
if (textParts.length > 0) {
|
|
335
360
|
assistantMsg.content = textParts.map((b) => b.text).join("\n");
|
|
336
361
|
}
|
|
362
|
+
const thinkingParts = msg.content.filter(
|
|
363
|
+
(b) => b.type === "thinking" && b.thinking
|
|
364
|
+
);
|
|
365
|
+
if (thinkingParts.length > 0) {
|
|
366
|
+
assistantMsg.reasoning_content = thinkingParts.map((b) => b.thinking).join("\n");
|
|
367
|
+
}
|
|
337
368
|
const toolUseParts = msg.content.filter(
|
|
338
369
|
(b) => b.type === "tool_use" && b.id
|
|
339
370
|
);
|
|
@@ -386,6 +417,13 @@ function transformOpenAIResponseToAnthropic(openaiResponse, originalModel) {
|
|
|
386
417
|
const choice = openaiResponse.choices?.[0];
|
|
387
418
|
if (!choice) throw new Error("No choices in OpenAI response");
|
|
388
419
|
const content = [];
|
|
420
|
+
if (choice.message?.reasoning_content) {
|
|
421
|
+
content.push({
|
|
422
|
+
type: "thinking",
|
|
423
|
+
thinking: choice.message.reasoning_content,
|
|
424
|
+
signature: ""
|
|
425
|
+
});
|
|
426
|
+
}
|
|
389
427
|
if (choice.message?.content) {
|
|
390
428
|
content.push({ type: "text", text: choice.message.content });
|
|
391
429
|
}
|
|
@@ -422,7 +460,8 @@ function transformOpenAIResponseToAnthropic(openaiResponse, originalModel) {
|
|
|
422
460
|
usage: {
|
|
423
461
|
input_tokens: (openaiResponse.usage?.prompt_tokens ?? 0) - (openaiResponse.usage?.prompt_tokens_details?.cached_tokens ?? 0),
|
|
424
462
|
output_tokens: openaiResponse.usage?.completion_tokens ?? 0,
|
|
425
|
-
cache_read_input_tokens: openaiResponse.usage?.prompt_tokens_details?.cached_tokens ?? 0
|
|
463
|
+
cache_read_input_tokens: openaiResponse.usage?.prompt_tokens_details?.cached_tokens ?? 0,
|
|
464
|
+
cache_creation_input_tokens: openaiResponse.usage?.prompt_tokens_details?.cache_creation_tokens ?? 0
|
|
426
465
|
}
|
|
427
466
|
};
|
|
428
467
|
}
|
|
@@ -445,7 +484,8 @@ data: ${JSON.stringify(data)}
|
|
|
445
484
|
usage: {
|
|
446
485
|
input_tokens: usage.input_tokens ?? 0,
|
|
447
486
|
output_tokens: 0,
|
|
448
|
-
cache_read_input_tokens: usage.cache_read_input_tokens ?? 0
|
|
487
|
+
cache_read_input_tokens: usage.cache_read_input_tokens ?? 0,
|
|
488
|
+
cache_creation_input_tokens: usage.cache_creation_input_tokens ?? 0
|
|
449
489
|
}
|
|
450
490
|
}
|
|
451
491
|
});
|
|
@@ -454,7 +494,7 @@ data: ${JSON.stringify(data)}
|
|
|
454
494
|
yield sse("content_block_start", {
|
|
455
495
|
type: "content_block_start",
|
|
456
496
|
index: i,
|
|
457
|
-
content_block: block.type === "tool_use" ? { type: "tool_use", id: block.id, name: block.name, input: {} } : { type: "text", text: "" }
|
|
497
|
+
content_block: block.type === "tool_use" ? { type: "tool_use", id: block.id, name: block.name, input: {} } : block.type === "thinking" ? { type: "thinking", thinking: "", signature: block.signature ?? "" } : { type: "text", text: "" }
|
|
458
498
|
});
|
|
459
499
|
if (block.type === "text" && block.text) {
|
|
460
500
|
yield sse("content_block_delta", {
|
|
@@ -462,6 +502,12 @@ data: ${JSON.stringify(data)}
|
|
|
462
502
|
index: i,
|
|
463
503
|
delta: { type: "text_delta", text: block.text }
|
|
464
504
|
});
|
|
505
|
+
} else if (block.type === "thinking" && block.thinking) {
|
|
506
|
+
yield sse("content_block_delta", {
|
|
507
|
+
type: "content_block_delta",
|
|
508
|
+
index: i,
|
|
509
|
+
delta: { type: "thinking_delta", thinking: block.thinking }
|
|
510
|
+
});
|
|
465
511
|
} else if (block.type === "tool_use" && block.input) {
|
|
466
512
|
yield sse("content_block_delta", {
|
|
467
513
|
type: "content_block_delta",
|
|
@@ -482,9 +528,183 @@ data: ${JSON.stringify(data)}
|
|
|
482
528
|
yield sse("message_stop", { type: "message_stop" });
|
|
483
529
|
}
|
|
484
530
|
|
|
531
|
+
// src/provider/kimi.ts
|
|
532
|
+
function transformAnthropicToKimi(body) {
|
|
533
|
+
debug(`transform: anthropic -> kimi model=${body.model} messages=${(body.messages ?? []).length}`);
|
|
534
|
+
const messages = [];
|
|
535
|
+
debug(`transform: anthropic -> kimi messageCount=${(body.messages ?? []).length}`);
|
|
536
|
+
if (body.system) {
|
|
537
|
+
const systemMsg = buildSystemMessage(body.system);
|
|
538
|
+
if (systemMsg) messages.push(systemMsg);
|
|
539
|
+
}
|
|
540
|
+
for (const msg of body.messages ?? []) {
|
|
541
|
+
if (typeof msg.content === "string") {
|
|
542
|
+
messages.push({ role: msg.role, content: msg.content });
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
if (!Array.isArray(msg.content)) {
|
|
546
|
+
messages.push({ role: msg.role, content: JSON.stringify(msg.content) });
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
if (msg.role === "user") {
|
|
550
|
+
const toolResults = msg.content.filter(
|
|
551
|
+
(b) => b.type === "tool_result" && b.tool_use_id
|
|
552
|
+
);
|
|
553
|
+
for (const tr of toolResults) {
|
|
554
|
+
messages.push({
|
|
555
|
+
role: "tool",
|
|
556
|
+
tool_call_id: sanitizeToolId(tr.tool_use_id),
|
|
557
|
+
content: typeof tr.content === "string" ? tr.content : Array.isArray(tr.content) ? tr.content.filter((b) => b.type === "text").map((b) => b.text).join("") : JSON.stringify(tr.content)
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
const contentParts = msg.content.filter(
|
|
561
|
+
(b) => b.type === "text" && b.text || b.type === "image" && (b.source?.type === "base64" && b.source.media_type && b.source.data || b.source?.type === "url" && b.source.url)
|
|
562
|
+
);
|
|
563
|
+
if (contentParts.length > 0) {
|
|
564
|
+
const converted = contentParts.map(convertAnthropicContentPart).filter(Boolean);
|
|
565
|
+
if (converted.length === 0) {
|
|
566
|
+
} else if (converted.every((p) => p.type === "text") && !converted.some((p) => p.cache_control)) {
|
|
567
|
+
messages.push({
|
|
568
|
+
role: "user",
|
|
569
|
+
content: converted.map((p) => p.text).join("")
|
|
570
|
+
});
|
|
571
|
+
} else {
|
|
572
|
+
messages.push({ role: "user", content: converted });
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
} else if (msg.role === "assistant") {
|
|
576
|
+
const assistantMsg = { role: "assistant", content: null };
|
|
577
|
+
const textParts = msg.content.filter(
|
|
578
|
+
(b) => b.type === "text" && b.text
|
|
579
|
+
);
|
|
580
|
+
if (textParts.length > 0) {
|
|
581
|
+
assistantMsg.content = textParts.map((b) => b.text).join("\n");
|
|
582
|
+
}
|
|
583
|
+
const thinkingParts = msg.content.filter(
|
|
584
|
+
(b) => b.type === "thinking" && b.thinking
|
|
585
|
+
);
|
|
586
|
+
const toolUseParts = msg.content.filter(
|
|
587
|
+
(b) => b.type === "tool_use" && b.id
|
|
588
|
+
);
|
|
589
|
+
if (toolUseParts.length > 0) {
|
|
590
|
+
assistantMsg.tool_calls = toolUseParts.map((b) => ({
|
|
591
|
+
id: sanitizeToolId(b.id),
|
|
592
|
+
type: "function",
|
|
593
|
+
function: {
|
|
594
|
+
name: b.name,
|
|
595
|
+
arguments: JSON.stringify(b.input ?? {})
|
|
596
|
+
}
|
|
597
|
+
}));
|
|
598
|
+
if (thinkingParts.length > 0) {
|
|
599
|
+
assistantMsg.reasoning_content = thinkingParts.map((b) => b.thinking).join("\n");
|
|
600
|
+
} else {
|
|
601
|
+
assistantMsg.reasoning_content = " ";
|
|
602
|
+
}
|
|
603
|
+
} else if (thinkingParts.length > 0) {
|
|
604
|
+
assistantMsg.reasoning_content = thinkingParts.map((b) => b.thinking).join("\n");
|
|
605
|
+
}
|
|
606
|
+
messages.push(assistantMsg);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
const result = {
|
|
610
|
+
model: body.model,
|
|
611
|
+
messages,
|
|
612
|
+
stream: body.stream ?? false
|
|
613
|
+
};
|
|
614
|
+
if (body.max_tokens != null) result.max_tokens = body.max_tokens;
|
|
615
|
+
if (body.temperature != null) result.temperature = body.temperature;
|
|
616
|
+
if (body.tools?.length) {
|
|
617
|
+
debug(`transform: mapping ${body.tools.length} tool(s)`);
|
|
618
|
+
result.tools = body.tools.map((t) => ({
|
|
619
|
+
type: "function",
|
|
620
|
+
function: {
|
|
621
|
+
name: t.name,
|
|
622
|
+
description: t.description ?? "",
|
|
623
|
+
parameters: t.input_schema
|
|
624
|
+
}
|
|
625
|
+
}));
|
|
626
|
+
if (body.tool_choice) {
|
|
627
|
+
const tc = body.tool_choice;
|
|
628
|
+
if (tc.type === "auto" || tc.type === "none" || tc.type === "required") {
|
|
629
|
+
result.tool_choice = tc.type;
|
|
630
|
+
} else if (tc.type === "tool") {
|
|
631
|
+
result.tool_choice = {
|
|
632
|
+
type: "function",
|
|
633
|
+
function: { name: tc.name }
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return result;
|
|
639
|
+
}
|
|
640
|
+
function transformKimiResponseToAnthropic(kimiResponse, originalModel) {
|
|
641
|
+
debug(`transform: kimi -> anthropic model=${kimiResponse.model ?? originalModel} choices=${kimiResponse.choices?.length ?? 0}`);
|
|
642
|
+
const choice = kimiResponse.choices?.[0];
|
|
643
|
+
if (!choice) throw new Error("No choices in Kimi response");
|
|
644
|
+
const content = [];
|
|
645
|
+
if (choice.message?.reasoning_content) {
|
|
646
|
+
content.push({
|
|
647
|
+
type: "thinking",
|
|
648
|
+
thinking: choice.message.reasoning_content,
|
|
649
|
+
signature: ""
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
if (choice.message?.content) {
|
|
653
|
+
content.push({ type: "text", text: choice.message.content });
|
|
654
|
+
}
|
|
655
|
+
if (choice.message?.tool_calls?.length) {
|
|
656
|
+
for (const tc of choice.message.tool_calls) {
|
|
657
|
+
let input = {};
|
|
658
|
+
try {
|
|
659
|
+
input = typeof tc.function.arguments === "string" ? JSON.parse(tc.function.arguments) : tc.function.arguments;
|
|
660
|
+
} catch {
|
|
661
|
+
input = { text: tc.function.arguments ?? "" };
|
|
662
|
+
}
|
|
663
|
+
content.push({
|
|
664
|
+
type: "tool_use",
|
|
665
|
+
id: tc.id,
|
|
666
|
+
name: tc.function.name,
|
|
667
|
+
input
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
const finishMap = {
|
|
672
|
+
stop: "end_turn",
|
|
673
|
+
length: "max_tokens",
|
|
674
|
+
tool_calls: "tool_use",
|
|
675
|
+
content_filter: "stop_sequence"
|
|
676
|
+
};
|
|
677
|
+
return {
|
|
678
|
+
id: kimiResponse.id ?? `msg_${Date.now()}`,
|
|
679
|
+
type: "message",
|
|
680
|
+
role: "assistant",
|
|
681
|
+
model: originalModel,
|
|
682
|
+
content,
|
|
683
|
+
stop_reason: finishMap[choice.finish_reason] ?? "end_turn",
|
|
684
|
+
stop_sequence: null,
|
|
685
|
+
usage: {
|
|
686
|
+
input_tokens: (kimiResponse.usage?.prompt_tokens ?? 0) - (kimiResponse.usage?.prompt_tokens_details?.cached_tokens ?? 0),
|
|
687
|
+
output_tokens: kimiResponse.usage?.completion_tokens ?? 0,
|
|
688
|
+
cache_read_input_tokens: kimiResponse.usage?.prompt_tokens_details?.cached_tokens ?? 0,
|
|
689
|
+
cache_creation_input_tokens: kimiResponse.usage?.prompt_tokens_details?.cache_creation_tokens ?? 0
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
|
|
485
694
|
// src/provider/server.ts
|
|
486
695
|
import http from "http";
|
|
487
|
-
|
|
696
|
+
import os3 from "os";
|
|
697
|
+
function getKimiHeaders() {
|
|
698
|
+
const platform = os3.platform();
|
|
699
|
+
const stainlessOS = platform === "darwin" ? "MacOS" : platform === "win32" ? "Windows" : "Linux";
|
|
700
|
+
return {
|
|
701
|
+
"X-Stainless-OS": stainlessOS,
|
|
702
|
+
"X-Stainless-Package-Version": "1.1.16",
|
|
703
|
+
"X-Stainless-Runtime": "node",
|
|
704
|
+
"User-Agent": "claude-code/1.0"
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
async function startOpenAIProxy(targetUrl, apiKey, model, models = [], modelMappings = {}, provider = "openai") {
|
|
488
708
|
const base = targetUrl.replace(/\/+$/, "");
|
|
489
709
|
const server = http.createServer(async (req, res) => {
|
|
490
710
|
debug(`Proxy request: ${req.method} ${req.url}`);
|
|
@@ -512,7 +732,8 @@ async function startOpenAIProxy(targetUrl, apiKey, model, models = [], modelMapp
|
|
|
512
732
|
const isStream = !!parsed.stream;
|
|
513
733
|
const requestModel = parsed.model ?? model;
|
|
514
734
|
const actualModel = modelMappings[requestModel] || requestModel;
|
|
515
|
-
const
|
|
735
|
+
const transformBody = provider === "kimi" ? transformAnthropicToKimi : transformAnthropicToOpenAI;
|
|
736
|
+
const openaiBody = transformBody({ ...parsed, model: actualModel, stream: false });
|
|
516
737
|
if (isStream) {
|
|
517
738
|
res.writeHead(200, {
|
|
518
739
|
"Content-Type": "text/event-stream",
|
|
@@ -525,7 +746,8 @@ async function startOpenAIProxy(targetUrl, apiKey, model, models = [], modelMapp
|
|
|
525
746
|
method: "POST",
|
|
526
747
|
headers: {
|
|
527
748
|
"Content-Type": "application/json",
|
|
528
|
-
"Authorization": `Bearer ${apiKey}
|
|
749
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
750
|
+
...provider === "kimi" ? getKimiHeaders() : {}
|
|
529
751
|
},
|
|
530
752
|
body: JSON.stringify(openaiBody)
|
|
531
753
|
});
|
|
@@ -540,7 +762,8 @@ data: ${errText}
|
|
|
540
762
|
return;
|
|
541
763
|
}
|
|
542
764
|
const data2 = await upstream2.json();
|
|
543
|
-
const
|
|
765
|
+
const transformResponse2 = provider === "kimi" ? transformKimiResponseToAnthropic : transformOpenAIResponseToAnthropic;
|
|
766
|
+
const anthropicResponse2 = transformResponse2(data2, parsed.model ?? model);
|
|
544
767
|
for (const chunk of synthesizeAnthropicSSE(anthropicResponse2)) {
|
|
545
768
|
res.write(chunk);
|
|
546
769
|
}
|
|
@@ -554,7 +777,8 @@ data: ${errText}
|
|
|
554
777
|
method: "POST",
|
|
555
778
|
headers: {
|
|
556
779
|
"Content-Type": "application/json",
|
|
557
|
-
"Authorization": `Bearer ${apiKey}
|
|
780
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
781
|
+
...provider === "kimi" ? getKimiHeaders() : {}
|
|
558
782
|
},
|
|
559
783
|
body: JSON.stringify(openaiBody)
|
|
560
784
|
});
|
|
@@ -566,7 +790,8 @@ data: ${errText}
|
|
|
566
790
|
return;
|
|
567
791
|
}
|
|
568
792
|
const data = await upstream.json();
|
|
569
|
-
const
|
|
793
|
+
const transformResponse = provider === "kimi" ? transformKimiResponseToAnthropic : transformOpenAIResponseToAnthropic;
|
|
794
|
+
const anthropicResponse = transformResponse(data, parsed.model ?? model);
|
|
570
795
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
571
796
|
res.end(JSON.stringify(anthropicResponse));
|
|
572
797
|
return;
|
|
@@ -615,6 +840,10 @@ var PROVIDERS = [
|
|
|
615
840
|
{
|
|
616
841
|
name: "openai",
|
|
617
842
|
description: "Embedded proxy \u2014 translates Anthropic requests to OpenAI Chat Completions format"
|
|
843
|
+
},
|
|
844
|
+
{
|
|
845
|
+
name: "kimi",
|
|
846
|
+
description: "Embedded proxy \u2014 translates Anthropic requests to Kimi API format (handles reasoning_content compatibility)"
|
|
618
847
|
}
|
|
619
848
|
];
|
|
620
849
|
var ANTHROPIC_ALIASES = ["claude-sonnet-4-6", "claude-opus-4-7", "claude-haiku-4-5"];
|
|
@@ -831,10 +1060,10 @@ function createPathCodec() {
|
|
|
831
1060
|
}
|
|
832
1061
|
|
|
833
1062
|
// src/config.ts
|
|
834
|
-
var CLAUDE_DIR = process.env.CLAUDE_DIR || path4.join(
|
|
1063
|
+
var CLAUDE_DIR = process.env.CLAUDE_DIR || path4.join(os4.homedir(), ".claude");
|
|
835
1064
|
var PROFILES_FILE = process.env.CLAUDE_PROFILES_FILE || path4.join(CLAUDE_DIR, "profiles.json");
|
|
836
1065
|
var SETTINGS_FILE = process.env.CLAUDE_SETTINGS_FILE || path4.join(CLAUDE_DIR, "settings.json");
|
|
837
|
-
var CLAUDE_JSON = path4.join(
|
|
1066
|
+
var CLAUDE_JSON = path4.join(os4.homedir(), ".claude.json");
|
|
838
1067
|
var PROJECTS_DIR = path4.join(CLAUDE_DIR, "projects");
|
|
839
1068
|
var SESSIONS_DIR = path4.join(CLAUDE_DIR, "sessions");
|
|
840
1069
|
var desktopApp = createDesktopApp();
|
|
@@ -996,15 +1225,16 @@ function execClaude(profileName, p, extraArgs) {
|
|
|
996
1225
|
}
|
|
997
1226
|
delete env.ANTHROPIC_API_KEY;
|
|
998
1227
|
info(`Launching Claude with profile '${profileName}': model=${firstModel || "(default)"} url=${p.url || "(default)"} provider=${p.provider || "anthropic"} binary=${binary}`);
|
|
999
|
-
if (p.provider === "openai") {
|
|
1228
|
+
if (p.provider === "openai" || p.provider === "kimi") {
|
|
1000
1229
|
const allModels = p.models || (p.model ? [p.model] : []);
|
|
1001
|
-
debug(`execClaude: starting
|
|
1230
|
+
debug(`execClaude: starting ${p.provider} proxy for ${allModels.length} model(s)`);
|
|
1002
1231
|
startOpenAIProxy(
|
|
1003
1232
|
p.url || "https://api.openai.com",
|
|
1004
1233
|
p.token || "",
|
|
1005
1234
|
firstModel || "gpt-4o",
|
|
1006
1235
|
allModels,
|
|
1007
|
-
{}
|
|
1236
|
+
{},
|
|
1237
|
+
p.provider
|
|
1008
1238
|
).then(({ baseUrl, stop }) => {
|
|
1009
1239
|
env.ANTHROPIC_BASE_URL = baseUrl;
|
|
1010
1240
|
debug(`execClaude: proxy running at ${baseUrl}`);
|
|
@@ -1311,7 +1541,7 @@ function profileCommand() {
|
|
|
1311
1541
|
ensureSettingsFile();
|
|
1312
1542
|
const settings2 = readJson(SETTINGS_FILE);
|
|
1313
1543
|
const exported = Object.fromEntries(
|
|
1314
|
-
Object.entries(settings2).filter(([key]) => !key.startsWith("_"))
|
|
1544
|
+
Object.entries(settings2).filter(([key]) => !key.startsWith("_") && key != "env")
|
|
1315
1545
|
);
|
|
1316
1546
|
const env = {
|
|
1317
1547
|
...typeof exported.env === "object" && exported.env !== null ? exported.env : {}
|