@adversity/coding-tool-x 3.0.1 → 3.0.3
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/web/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<link rel="icon" href="/favicon.ico">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>CC-TOOL - ClaudeCode增强工作助手</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-BDN4_LfP.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/vue-vendor-6JaYHOiI.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/vendors-D2HHw_aW.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/icons-BlzwYoRU.js">
|
package/package.json
CHANGED
|
@@ -52,26 +52,47 @@ const PROVIDER_CAPABILITIES = {
|
|
|
52
52
|
* @returns {string} - 'claude' | 'codex' | 'gemini' | 'openai_compatible'
|
|
53
53
|
*/
|
|
54
54
|
function detectChannelType(channel) {
|
|
55
|
-
|
|
55
|
+
try {
|
|
56
|
+
// Parse the URL to extract hostname
|
|
57
|
+
const parsedUrl = new URL(channel.baseUrl);
|
|
58
|
+
const hostname = parsedUrl.hostname.toLowerCase();
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
// Check if it's official Anthropic API (hostname only, not path)
|
|
61
|
+
if (hostname.includes('anthropic.com') || hostname.includes('claude.ai')) {
|
|
62
|
+
return 'claude';
|
|
63
|
+
}
|
|
61
64
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
// Check if it's Gemini (hostname only)
|
|
66
|
+
if (hostname.includes('generativelanguage.googleapis.com') || hostname.includes('gemini')) {
|
|
67
|
+
return 'gemini';
|
|
68
|
+
}
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
// Check if it's OpenAI official (hostname only)
|
|
71
|
+
if (hostname.includes('api.openai.com')) {
|
|
72
|
+
return 'codex';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// All other third-party proxies default to OpenAI compatible
|
|
76
|
+
// Including: 88code, anyrouter, internal proxies, etc.
|
|
77
|
+
// This correctly handles URLs like https://code.newcli.com/claude/aws
|
|
78
|
+
return 'openai_compatible';
|
|
79
|
+
} catch (error) {
|
|
80
|
+
// If URL parsing fails, fall back to string matching on full URL
|
|
81
|
+
console.warn(`[ModelDetector] Failed to parse URL ${channel.baseUrl}: ${error.message}`);
|
|
82
|
+
const baseUrl = channel.baseUrl.toLowerCase();
|
|
83
|
+
|
|
84
|
+
if (baseUrl.includes('anthropic.com') || baseUrl.includes('claude.ai')) {
|
|
85
|
+
return 'claude';
|
|
86
|
+
}
|
|
87
|
+
if (baseUrl.includes('generativelanguage.googleapis.com')) {
|
|
88
|
+
return 'gemini';
|
|
89
|
+
}
|
|
90
|
+
if (baseUrl.includes('api.openai.com')) {
|
|
91
|
+
return 'codex';
|
|
92
|
+
}
|
|
71
93
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return 'openai_compatible';
|
|
94
|
+
return 'openai_compatible';
|
|
95
|
+
}
|
|
75
96
|
}
|
|
76
97
|
|
|
77
98
|
// Model name normalization mapping
|
|
@@ -509,14 +530,53 @@ async function fetchModelsFromProvider(channel, channelType) {
|
|
|
509
530
|
});
|
|
510
531
|
}
|
|
511
532
|
} else if (res.statusCode === 401 || res.statusCode === 403) {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
533
|
+
// Check if it's a Cloudflare protection issue
|
|
534
|
+
const bodyLower = data.toLowerCase();
|
|
535
|
+
const isCloudflare = bodyLower.includes('cloudflare') || bodyLower.includes('challenge') || bodyLower.includes('cf-ray');
|
|
536
|
+
|
|
537
|
+
let errorMessage;
|
|
538
|
+
let errorHint;
|
|
539
|
+
|
|
540
|
+
if (isCloudflare) {
|
|
541
|
+
errorMessage = 'Cloudflare 防护拦截,已使用默认模型';
|
|
542
|
+
errorHint = '该 API 端点受 Cloudflare 保护,已自动使用默认模型 claude-sonnet-4-5';
|
|
543
|
+
console.warn(`[ModelDetector] Cloudflare protection detected for ${channel.name}, using default model`);
|
|
544
|
+
resolve({
|
|
545
|
+
models: ['claude-sonnet-4-5'],
|
|
546
|
+
supported: true,
|
|
547
|
+
cached: false,
|
|
548
|
+
fallbackUsed: true,
|
|
549
|
+
error: errorMessage,
|
|
550
|
+
errorHint: errorHint,
|
|
551
|
+
statusCode: res.statusCode
|
|
552
|
+
});
|
|
553
|
+
} else if (res.statusCode === 401) {
|
|
554
|
+
errorMessage = 'API 密钥认证失败';
|
|
555
|
+
errorHint = '请检查 API 密钥是否正确配置';
|
|
556
|
+
console.error(`[ModelDetector] Authentication failed for ${channel.name}: ${res.statusCode} - ${errorMessage}`);
|
|
557
|
+
resolve({
|
|
558
|
+
models: [],
|
|
559
|
+
supported: true,
|
|
560
|
+
cached: false,
|
|
561
|
+
fallbackUsed: true,
|
|
562
|
+
error: errorMessage,
|
|
563
|
+
errorHint: errorHint,
|
|
564
|
+
statusCode: res.statusCode
|
|
565
|
+
});
|
|
566
|
+
} else {
|
|
567
|
+
errorMessage = '访问被拒绝';
|
|
568
|
+
errorHint = '请检查 API 密钥权限或联系服务提供商';
|
|
569
|
+
console.error(`[ModelDetector] Access denied for ${channel.name}: ${res.statusCode} - ${errorMessage}`);
|
|
570
|
+
resolve({
|
|
571
|
+
models: [],
|
|
572
|
+
supported: true,
|
|
573
|
+
cached: false,
|
|
574
|
+
fallbackUsed: true,
|
|
575
|
+
error: errorMessage,
|
|
576
|
+
errorHint: errorHint,
|
|
577
|
+
statusCode: res.statusCode
|
|
578
|
+
});
|
|
579
|
+
}
|
|
520
580
|
} else if (res.statusCode === 404) {
|
|
521
581
|
console.warn(`[ModelDetector] Model list endpoint not found for ${channel.name}`);
|
|
522
582
|
resolve({
|
|
@@ -524,7 +584,9 @@ async function fetchModelsFromProvider(channel, channelType) {
|
|
|
524
584
|
supported: false,
|
|
525
585
|
cached: false,
|
|
526
586
|
fallbackUsed: true,
|
|
527
|
-
error: '
|
|
587
|
+
error: '模型列表端点不存在',
|
|
588
|
+
errorHint: '该 API 可能不支持 /v1/models 接口,请手动输入模型名称',
|
|
589
|
+
statusCode: 404
|
|
528
590
|
});
|
|
529
591
|
} else if (res.statusCode === 429) {
|
|
530
592
|
console.warn(`[ModelDetector] Rate limited for ${channel.name}`);
|
|
@@ -533,7 +595,9 @@ async function fetchModelsFromProvider(channel, channelType) {
|
|
|
533
595
|
supported: true,
|
|
534
596
|
cached: false,
|
|
535
597
|
fallbackUsed: true,
|
|
536
|
-
error: '
|
|
598
|
+
error: '请求频率限制',
|
|
599
|
+
errorHint: '请稍后再试或联系服务提供商提高限额',
|
|
600
|
+
statusCode: 429
|
|
537
601
|
});
|
|
538
602
|
} else {
|
|
539
603
|
console.error(`[ModelDetector] Unexpected status ${res.statusCode} for ${channel.name}`);
|
|
@@ -542,7 +606,9 @@ async function fetchModelsFromProvider(channel, channelType) {
|
|
|
542
606
|
supported: true,
|
|
543
607
|
cached: false,
|
|
544
608
|
fallbackUsed: true,
|
|
545
|
-
error: `HTTP ${res.statusCode}
|
|
609
|
+
error: `HTTP 错误 ${res.statusCode}`,
|
|
610
|
+
errorHint: '请检查 API 端点配置或联系服务提供商',
|
|
611
|
+
statusCode: res.statusCode
|
|
546
612
|
});
|
|
547
613
|
}
|
|
548
614
|
});
|