coding-tool-x 3.6.10 → 3.6.12
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/README.md +6 -8
- package/dist/web/assets/{Analytics-vN7CJLtB.js → Analytics-BuBlsbcI.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-D8w_9p6Z.js → ConfigTemplates-DQczxuOX.js} +1 -1
- package/dist/web/assets/Home-BvAzzWnB.js +1 -0
- package/dist/web/assets/Home-CIua-b-o.css +1 -0
- package/dist/web/assets/{PluginManager-vFp_miHj.js → PluginManager-C8gAlaps.js} +1 -1
- package/dist/web/assets/{ProjectList-DDfNp6CO.js → ProjectList-nqgi6_cR.js} +1 -1
- package/dist/web/assets/{SessionList-Cit8Ylm_.js → SessionList-D8AxMYy6.js} +1 -1
- package/dist/web/assets/{SkillManager-Cp0EigHc.js → SkillManager-BDbNbNkK.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-DPTYHnp4.js → WorkspaceManager-DGGaGW2c.js} +1 -1
- package/dist/web/assets/index-Dsh4Q5Cg.css +1 -0
- package/dist/web/assets/index-y-eEayxR.js +2 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/commands/daemon.js +3 -1
- package/src/commands/ui.js +4 -3
- package/src/index.js +11 -0
- package/src/server/api/config-export.js +12 -2
- package/src/server/index.js +0 -15
- package/src/server/services/channel-balance.js +0 -147
- package/src/server/services/config-export-service.js +692 -4
- package/src/server/services/plugins-service.js +1 -17
- package/src/utils/cli-flags.js +7 -0
- package/dist/web/assets/Home-BdyDRjGR.js +0 -1
- package/dist/web/assets/Home-BspgEJBb.css +0 -1
- package/dist/web/assets/index-CfBxeWy0.js +0 -2
- package/dist/web/assets/index-Dl2Bz258.css +0 -1
package/dist/web/index.html
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
<link rel="icon" href="/favicon.ico">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>coding-tool-x · AI 编程工作台</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-y-eEayxR.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/markdown-BNJfEgCA.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/vue-vendor-B5RqjEjQ.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/naive-ui-kcWDeJwl.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/icons-QFXzEgqM.js">
|
|
13
13
|
<link rel="modulepreload" crossorigin href="/assets/vendors-DQA4Hw9v.js">
|
|
14
14
|
<link rel="stylesheet" crossorigin href="/assets/markdown-BfC0goYb.css">
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Dsh4Q5Cg.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="app"></div>
|
package/package.json
CHANGED
package/src/commands/daemon.js
CHANGED
|
@@ -11,6 +11,7 @@ const {
|
|
|
11
11
|
getPortToolIssue,
|
|
12
12
|
formatPortToolIssue
|
|
13
13
|
} = require('../utils/port-helper');
|
|
14
|
+
const { hasHostFlag } = require('../utils/cli-flags');
|
|
14
15
|
|
|
15
16
|
const PM2_APP_NAME = 'cc-tool';
|
|
16
17
|
const STARTUP_LOG_FILE = 'cc-tool-out.log';
|
|
@@ -499,7 +500,7 @@ async function handleStart() {
|
|
|
499
500
|
try {
|
|
500
501
|
const config = loadConfig();
|
|
501
502
|
const port = config.ports?.webUI || 19999;
|
|
502
|
-
const enableHost =
|
|
503
|
+
const enableHost = hasHostFlag();
|
|
503
504
|
const enableHttps = process.argv.includes('--https');
|
|
504
505
|
fs.mkdirSync(PATHS.logs, { recursive: true });
|
|
505
506
|
|
|
@@ -733,6 +734,7 @@ module.exports = {
|
|
|
733
734
|
_test: {
|
|
734
735
|
detectStalePm2RuntimeIssue,
|
|
735
736
|
extractMissingPm2ForkScriptPath,
|
|
737
|
+
buildStartOptions,
|
|
736
738
|
shouldTreatPortOwnershipAsReady,
|
|
737
739
|
getManagedPorts,
|
|
738
740
|
shouldStopPM2Process
|
package/src/commands/ui.js
CHANGED
|
@@ -3,13 +3,14 @@ const { startServer } = require('../server');
|
|
|
3
3
|
const open = require('open');
|
|
4
4
|
const { getProxyStatus } = require('../server/proxy-server');
|
|
5
5
|
const { loadConfig } = require('../config/loader');
|
|
6
|
+
const { hasHostFlag } = require('../utils/cli-flags');
|
|
6
7
|
|
|
7
8
|
async function handleUI() {
|
|
8
9
|
// 检查是否为 daemon 模式(PM2 启动)
|
|
9
10
|
const isDaemon = process.argv.includes('--daemon');
|
|
10
11
|
|
|
11
|
-
// 检查是否启用 LAN 访问 (--host 标志)
|
|
12
|
-
const enableHost =
|
|
12
|
+
// 检查是否启用 LAN 访问 (--host/--hosts 标志)
|
|
13
|
+
const enableHost = hasHostFlag();
|
|
13
14
|
const enableHttps = process.argv.includes('--https');
|
|
14
15
|
const host = enableHost ? '0.0.0.0' : '127.0.0.1';
|
|
15
16
|
const protocol = enableHttps ? 'https' : 'http';
|
|
@@ -18,7 +19,7 @@ async function handleUI() {
|
|
|
18
19
|
console.clear();
|
|
19
20
|
console.log(chalk.cyan.bold('\n[NET] 启动 Coding-Tool Web UI...\n'));
|
|
20
21
|
if (enableHost) {
|
|
21
|
-
console.log(chalk.yellow('[WARN] LAN 访问已启用 (--host)\n'));
|
|
22
|
+
console.log(chalk.yellow('[WARN] LAN 访问已启用 (--host/--hosts)\n'));
|
|
22
23
|
}
|
|
23
24
|
if (enableHttps) {
|
|
24
25
|
console.log(chalk.yellow('[LOCK] 已启用本地 HTTPS 模式 (--https)\n'));
|
package/src/index.js
CHANGED
|
@@ -16,6 +16,7 @@ const { handleUpdate } = require('./commands/update');
|
|
|
16
16
|
const { ensureStorageDirMigrated } = require('./config/paths');
|
|
17
17
|
const PluginManager = require('./plugins/plugin-manager');
|
|
18
18
|
const eventBus = require('./plugins/event-bus');
|
|
19
|
+
const { hasHostFlag } = require('./utils/cli-flags');
|
|
19
20
|
const chalk = require('chalk');
|
|
20
21
|
const path = require('path');
|
|
21
22
|
const fs = require('fs');
|
|
@@ -53,9 +54,12 @@ function showHelp() {
|
|
|
53
54
|
console.log(' ctx ui 前台启动 Web UI(仅本地访问)');
|
|
54
55
|
console.log(' ctx ui --https 前台启动 Web UI(本地 HTTPS)');
|
|
55
56
|
console.log(' ctx ui --host 前台启动 Web UI(允许 LAN 访问)');
|
|
57
|
+
console.log(' ctx ui --hosts 前台启动 Web UI(同 --host)');
|
|
58
|
+
console.log(' ctx --hosts 前台启动 Web UI(同 ctx ui --host)');
|
|
56
59
|
console.log(' ctx ui start 后台启动 Web UI');
|
|
57
60
|
console.log(' ctx ui start --https 后台启动 Web UI(本地 HTTPS)');
|
|
58
61
|
console.log(' ctx ui start --host 后台启动 Web UI(允许 LAN 访问)');
|
|
62
|
+
console.log(' ctx ui start --hosts 后台启动 Web UI(同 --host)');
|
|
59
63
|
console.log(' ctx ui stop 停止 Web UI');
|
|
60
64
|
console.log(' ctx ui restart 重启 Web UI\n');
|
|
61
65
|
|
|
@@ -156,6 +160,13 @@ async function main() {
|
|
|
156
160
|
return;
|
|
157
161
|
}
|
|
158
162
|
|
|
163
|
+
// LAN 快捷入口,等同于 ctx ui --host/--hosts
|
|
164
|
+
if (hasHostFlag(process.argv) && !args.some((arg) => arg && !arg.startsWith('-'))) {
|
|
165
|
+
const { handleUI } = require('./commands/ui');
|
|
166
|
+
await handleUI();
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
159
170
|
// daemon 命令兼容(保持与 README 中旧命令一致)
|
|
160
171
|
if (args[0] === 'daemon') {
|
|
161
172
|
const subCommand = args[1] || 'status';
|
|
@@ -31,6 +31,15 @@ function resolveChannelsByType(exportData) {
|
|
|
31
31
|
|
|
32
32
|
function buildPreviewSummary(data) {
|
|
33
33
|
const channelsByType = resolveChannelsByType(data);
|
|
34
|
+
const pluginsByPlatform = data?.data?.pluginsByPlatform && typeof data.data.pluginsByPlatform === 'object'
|
|
35
|
+
? data.data.pluginsByPlatform
|
|
36
|
+
: {};
|
|
37
|
+
const platformPlugins = Object.values(pluginsByPlatform).flatMap((snapshot) => (
|
|
38
|
+
Array.isArray(snapshot?.plugins) ? snapshot.plugins : []
|
|
39
|
+
));
|
|
40
|
+
const plugins = platformPlugins.length > 0
|
|
41
|
+
? platformPlugins
|
|
42
|
+
: (Array.isArray(data.data.plugins) ? data.data.plugins : []);
|
|
34
43
|
const allChannels = [
|
|
35
44
|
...channelsByType.claude.map(c => ({ ...c, type: c.type || 'claude' })),
|
|
36
45
|
...channelsByType.codex.map(c => ({ ...c, type: c.type || 'codex' })),
|
|
@@ -44,7 +53,7 @@ function buildPreviewSummary(data) {
|
|
|
44
53
|
counts: {
|
|
45
54
|
configTemplates: (data.data.configTemplates || []).length,
|
|
46
55
|
channels: allChannels.length,
|
|
47
|
-
plugins:
|
|
56
|
+
plugins: plugins.length
|
|
48
57
|
},
|
|
49
58
|
items: {
|
|
50
59
|
configTemplates: (data.data.configTemplates || []).map(t => ({
|
|
@@ -57,9 +66,10 @@ function buildPreviewSummary(data) {
|
|
|
57
66
|
name: c.name,
|
|
58
67
|
type: c.type
|
|
59
68
|
})),
|
|
60
|
-
plugins:
|
|
69
|
+
plugins: plugins.map(p => ({
|
|
61
70
|
name: p.name,
|
|
62
71
|
type: p.type,
|
|
72
|
+
platform: p.platform,
|
|
63
73
|
version: p.version
|
|
64
74
|
}))
|
|
65
75
|
}
|
package/src/server/index.js
CHANGED
|
@@ -23,7 +23,6 @@ const { startProxyServer } = require('./proxy-server');
|
|
|
23
23
|
const { startCodexProxyServer } = require('./codex-proxy-server');
|
|
24
24
|
const { startGeminiProxyServer } = require('./gemini-proxy-server');
|
|
25
25
|
const { startOpenCodeProxyServer, collectProxyModelList } = require('./opencode-proxy-server');
|
|
26
|
-
const { createRemoteMutationGuard } = require('./services/network-access');
|
|
27
26
|
const { createApiRequestLogger } = require('./services/request-logger');
|
|
28
27
|
const { inspectWebBuildState, ensureWebDistReady } = require('./services/web-build');
|
|
29
28
|
const { ensureHttpsCredentials } = require('./services/https-cert');
|
|
@@ -149,8 +148,6 @@ async function startServer(port, host = '127.0.0.1', options = {}) {
|
|
|
149
148
|
|
|
150
149
|
const app = express();
|
|
151
150
|
const useHttps = options.useHttps === true || process.argv.includes('--https');
|
|
152
|
-
const lanMode = host === '0.0.0.0';
|
|
153
|
-
const allowRemoteMutation = process.env.CC_TOOL_ALLOW_REMOTE_WRITE === 'true';
|
|
154
151
|
|
|
155
152
|
// Middleware
|
|
156
153
|
app.use(express.json({ limit: '100mb' }));
|
|
@@ -170,15 +167,6 @@ async function startServer(port, host = '127.0.0.1', options = {}) {
|
|
|
170
167
|
// API 请求日志(由 CC_TOOL_LOG_API_REQUESTS=true 环境变量控制,默认关闭)
|
|
171
168
|
app.use('/api', createApiRequestLogger());
|
|
172
169
|
|
|
173
|
-
if (lanMode) {
|
|
174
|
-
app.use('/api', createRemoteMutationGuard({
|
|
175
|
-
enabled: true,
|
|
176
|
-
allowRemoteMutation,
|
|
177
|
-
message: '出于安全考虑,LAN 模式默认仅允许本机执行写操作。可设置 CC_TOOL_ALLOW_REMOTE_WRITE=true 覆盖。'
|
|
178
|
-
}));
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
170
|
// API Routes
|
|
183
171
|
app.use('/api/projects', require('./api/projects')(config));
|
|
184
172
|
app.use('/api/sessions', require('./api/sessions')(config));
|
|
@@ -316,9 +304,6 @@ async function startServer(port, host = '127.0.0.1', options = {}) {
|
|
|
316
304
|
console.log(chalk.gray(' [TIP] 首次访问自签名证书时,浏览器可能会提示手动信任本地证书'));
|
|
317
305
|
}
|
|
318
306
|
|
|
319
|
-
if (host === '0.0.0.0' && !allowRemoteMutation) {
|
|
320
|
-
console.log(chalk.yellow(' [LOCK] 已启用 LAN 安全保护:远程写操作默认禁用'));
|
|
321
|
-
}
|
|
322
307
|
// 自动恢复代理状态
|
|
323
308
|
autoRestoreProxies();
|
|
324
309
|
|
|
@@ -12,7 +12,6 @@ const REQUEST_TIMEOUT_MS = 8000;
|
|
|
12
12
|
const MAX_RESPONSE_BYTES = 1024 * 1024;
|
|
13
13
|
const QUOTA_UNIT = 500000;
|
|
14
14
|
const VELOERA_QUOTA_UNIT = 1000000;
|
|
15
|
-
const NEWCLI_QUOTA_UNIT = 1000000;
|
|
16
15
|
const VALID_SOURCES = new Set(['claude', 'codex', 'gemini', 'opencode']);
|
|
17
16
|
const GATEWAY_PATH_SEGMENTS = new Set(['openai', 'anthropic', 'claude', 'gemini', 'codex']);
|
|
18
17
|
const HUB_PLATFORMS = new Set(['new-api', 'one-api', 'one-hub', 'done-hub', 'veloera', 'anyrouter', 'aihubmix']);
|
|
@@ -416,7 +415,6 @@ async function tryRequestJson(url, options) {
|
|
|
416
415
|
function detectPlatformByUrlHint(...values) {
|
|
417
416
|
const value = values.map(item => String(item || '')).join(' ').toLowerCase();
|
|
418
417
|
if (value.includes('88code') || value.includes('88-code') || value.includes('rainapp.top')) return '88code';
|
|
419
|
-
if (value.includes('code.newcli.com') || value.includes('newcli') || value.includes('new-cli')) return 'newcli';
|
|
420
418
|
if (value.includes('openrouter.ai') || value.includes('openrouter')) return 'openrouter';
|
|
421
419
|
if (value.includes('aihubmix')) return 'aihubmix';
|
|
422
420
|
if (value.includes('dashscope') || value.includes('dashscope.aliyuncs.com') || value.includes('compatible-mode')) return 'dashscope';
|
|
@@ -602,77 +600,6 @@ function buildSiliconFlowUserInfoSnapshot(payload) {
|
|
|
602
600
|
});
|
|
603
601
|
}
|
|
604
602
|
|
|
605
|
-
function normalizeNewCliQuotaUnit(value) {
|
|
606
|
-
return normalizeQuotaUnit(value, NEWCLI_QUOTA_UNIT);
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
function extractNewCliSubscriptionItems(payload) {
|
|
610
|
-
if (!payload || typeof payload !== 'object') return [];
|
|
611
|
-
const data = payload.data && typeof payload.data === 'object' ? payload.data : payload;
|
|
612
|
-
const subscription = data.subscription && typeof data.subscription === 'object' ? data.subscription : data;
|
|
613
|
-
const candidates = [
|
|
614
|
-
subscription.active,
|
|
615
|
-
subscription.subscriptions,
|
|
616
|
-
subscription.items,
|
|
617
|
-
data.subscriptions,
|
|
618
|
-
data.items,
|
|
619
|
-
Array.isArray(subscription) ? subscription : null,
|
|
620
|
-
Array.isArray(data) ? data : null
|
|
621
|
-
];
|
|
622
|
-
for (const candidate of candidates) {
|
|
623
|
-
if (Array.isArray(candidate)) return candidate;
|
|
624
|
-
}
|
|
625
|
-
return [];
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
function shouldUseNewCliSubscription(item = {}) {
|
|
629
|
-
if (!item || typeof item !== 'object') return false;
|
|
630
|
-
if (item.isActive === false) return false;
|
|
631
|
-
const status = String(item.status || item.subscriptionStatus || '').trim().toUpperCase();
|
|
632
|
-
return !status || status === 'ACTIVE' || status === '活跃中';
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
function buildNewCliDashboardSnapshot(payload) {
|
|
636
|
-
const items = extractNewCliSubscriptionItems(payload).filter(shouldUseNewCliSubscription);
|
|
637
|
-
if (!items.length) return makeHiddenSnapshot('newcli');
|
|
638
|
-
|
|
639
|
-
const data = payload?.data && typeof payload.data === 'object' ? payload.data : payload;
|
|
640
|
-
const unit = normalizeNewCliQuotaUnit(data?.quotaUnit || data?.quota_unit || data?.quota_per_unit || data?.quotaPerUnit);
|
|
641
|
-
let remainingRaw = 0;
|
|
642
|
-
let usedRaw = 0;
|
|
643
|
-
let totalRaw = 0;
|
|
644
|
-
let hasRemaining = false;
|
|
645
|
-
let hasTotal = false;
|
|
646
|
-
|
|
647
|
-
for (const item of items) {
|
|
648
|
-
const plan = item.plan && typeof item.plan === 'object' ? item.plan : {};
|
|
649
|
-
const remaining = readMoneyField(item, 'quotaRemaining', 'quota_remaining', 'remainingQuota', 'remaining_quota');
|
|
650
|
-
const used = readMoneyField(item, 'quotaUsed', 'quota_used', 'usedQuota', 'used_quota') || 0;
|
|
651
|
-
const limit = readMoneyField(item, 'quotaLimit', 'quota_limit')
|
|
652
|
-
?? readMoneyField(plan, 'quotaLimit', 'quota_limit');
|
|
653
|
-
|
|
654
|
-
if (remaining != null) {
|
|
655
|
-
hasRemaining = true;
|
|
656
|
-
remainingRaw += Math.max(0, remaining);
|
|
657
|
-
usedRaw += Math.max(0, used);
|
|
658
|
-
if (limit != null) {
|
|
659
|
-
hasTotal = true;
|
|
660
|
-
totalRaw += Math.max(0, limit);
|
|
661
|
-
} else {
|
|
662
|
-
totalRaw += Math.max(0, remaining + used);
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
if (!hasRemaining) return makeHiddenSnapshot('newcli');
|
|
668
|
-
|
|
669
|
-
return makeVisibleSnapshot('newcli', {
|
|
670
|
-
remaining: remainingRaw / unit,
|
|
671
|
-
used: usedRaw / unit,
|
|
672
|
-
total: (hasTotal || usedRaw > 0) ? totalRaw / unit : undefined
|
|
673
|
-
});
|
|
674
|
-
}
|
|
675
|
-
|
|
676
603
|
function extractQuotaUnitFromStatus(payload) {
|
|
677
604
|
if (!payload || typeof payload !== 'object') return null;
|
|
678
605
|
const data = payload.data && typeof payload.data === 'object' ? payload.data : payload;
|
|
@@ -864,41 +791,6 @@ function buildSiliconFlowApiBaseCandidates(baseUrl, channel = {}) {
|
|
|
864
791
|
return candidates;
|
|
865
792
|
}
|
|
866
793
|
|
|
867
|
-
function buildNewCliWebBaseCandidates(baseUrl, channel = {}) {
|
|
868
|
-
const candidates = [];
|
|
869
|
-
const inputs = [
|
|
870
|
-
channel.balanceBaseUrl,
|
|
871
|
-
channel.websiteUrl,
|
|
872
|
-
channel.baseUrl,
|
|
873
|
-
baseUrl
|
|
874
|
-
].filter(Boolean);
|
|
875
|
-
|
|
876
|
-
for (const input of inputs) {
|
|
877
|
-
try {
|
|
878
|
-
const parsed = new URL(input);
|
|
879
|
-
addUnique(candidates, parsed.origin);
|
|
880
|
-
} catch {}
|
|
881
|
-
}
|
|
882
|
-
return candidates;
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
function buildNewCliAuthHeaderCandidates(token) {
|
|
886
|
-
const raw = stripBearer(token).replace(/^cookie:\s*/i, '').trim();
|
|
887
|
-
if (!raw) return [];
|
|
888
|
-
if (raw.includes('=')) {
|
|
889
|
-
return [{
|
|
890
|
-
Accept: 'application/json',
|
|
891
|
-
Cookie: raw
|
|
892
|
-
}];
|
|
893
|
-
}
|
|
894
|
-
return [
|
|
895
|
-
buildAuthHeaders(raw),
|
|
896
|
-
{ Accept: 'application/json', Cookie: `auth_token=${raw}` },
|
|
897
|
-
{ Accept: 'application/json', Cookie: `session=${raw}` },
|
|
898
|
-
{ Accept: 'application/json', Cookie: `__Secure-authjs.session-token=${raw}` }
|
|
899
|
-
];
|
|
900
|
-
}
|
|
901
|
-
|
|
902
794
|
function hasGatewayPathSegment(value) {
|
|
903
795
|
try {
|
|
904
796
|
const parsed = new URL(normalizeBaseUrl(value));
|
|
@@ -1155,27 +1047,12 @@ function buildBalanceProbeStrategies(baseUrl, channel = {}, token = '') {
|
|
|
1155
1047
|
add({ type: 'siliconflow-user-info', baseUrl, apiBase });
|
|
1156
1048
|
}
|
|
1157
1049
|
};
|
|
1158
|
-
const addNewCliStrategies = () => {
|
|
1159
|
-
for (const webBase of buildNewCliWebBaseCandidates(baseUrl, channel)) {
|
|
1160
|
-
add({
|
|
1161
|
-
type: 'newcli-dashboard',
|
|
1162
|
-
baseUrl,
|
|
1163
|
-
webBase,
|
|
1164
|
-
requiresDedicatedToken: !hasDedicatedBalanceToken(channel)
|
|
1165
|
-
});
|
|
1166
|
-
}
|
|
1167
|
-
};
|
|
1168
1050
|
|
|
1169
1051
|
if (UNSUPPORTED_BALANCE_PLATFORMS.has(hintedPlatform)) {
|
|
1170
1052
|
add({ type: 'unsupported-balance', platform: hintedPlatform, baseUrl });
|
|
1171
1053
|
return strategies;
|
|
1172
1054
|
}
|
|
1173
1055
|
|
|
1174
|
-
if (hintedPlatform === 'newcli') {
|
|
1175
|
-
addNewCliStrategies();
|
|
1176
|
-
return strategies;
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
1056
|
if (hintedPlatform === 'siliconflow') {
|
|
1180
1057
|
addSiliconFlowStrategies();
|
|
1181
1058
|
return strategies;
|
|
@@ -1347,21 +1224,6 @@ async function runSiliconFlowUserInfoStrategy(strategy, token) {
|
|
|
1347
1224
|
return buildSiliconFlowUserInfoSnapshot(payload);
|
|
1348
1225
|
}
|
|
1349
1226
|
|
|
1350
|
-
async function runNewCliDashboardStrategy(strategy, token, channel = {}) {
|
|
1351
|
-
if (strategy.requiresDedicatedToken || !hasDedicatedBalanceToken(channel)) {
|
|
1352
|
-
return makeHiddenSnapshot('newcli');
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
for (const headers of buildNewCliAuthHeaderCandidates(token)) {
|
|
1356
|
-
const payload = await tryRequestJson(joinUrl(strategy.webBase || strategy.baseUrl, '/api/user/dashboard'), {
|
|
1357
|
-
headers
|
|
1358
|
-
});
|
|
1359
|
-
const snapshot = buildNewCliDashboardSnapshot(payload);
|
|
1360
|
-
if (snapshot.visible) return snapshot;
|
|
1361
|
-
}
|
|
1362
|
-
return makeHiddenSnapshot('newcli');
|
|
1363
|
-
}
|
|
1364
|
-
|
|
1365
1227
|
async function runBalanceStrategy(strategy, token, channel = {}) {
|
|
1366
1228
|
if (!strategy || !strategy.type) {
|
|
1367
1229
|
return { snapshot: makeHiddenSnapshot(), strategy };
|
|
@@ -1433,12 +1295,6 @@ async function runBalanceStrategy(strategy, token, channel = {}) {
|
|
|
1433
1295
|
strategy
|
|
1434
1296
|
};
|
|
1435
1297
|
}
|
|
1436
|
-
if (strategy.type === 'newcli-dashboard') {
|
|
1437
|
-
return {
|
|
1438
|
-
snapshot: await runNewCliDashboardStrategy(strategy, token, channel),
|
|
1439
|
-
strategy
|
|
1440
|
-
};
|
|
1441
|
-
}
|
|
1442
1298
|
|
|
1443
1299
|
return { snapshot: makeHiddenSnapshot(), strategy };
|
|
1444
1300
|
}
|
|
@@ -1464,7 +1320,6 @@ async function probeBalanceFromBase(baseUrl, channel, token) {
|
|
|
1464
1320
|
strategy.type?.startsWith('88code') ? '88code'
|
|
1465
1321
|
: strategy.type?.startsWith('openrouter') ? 'openrouter'
|
|
1466
1322
|
: strategy.type?.startsWith('siliconflow') ? 'siliconflow'
|
|
1467
|
-
: strategy.type?.startsWith('newcli') ? 'newcli'
|
|
1468
1323
|
: strategy.type?.startsWith('sub2api') ? 'sub2api'
|
|
1469
1324
|
: strategy.platform || null
|
|
1470
1325
|
);
|
|
@@ -1731,10 +1586,8 @@ module.exports = {
|
|
|
1731
1586
|
build88CodeApiBaseCandidates,
|
|
1732
1587
|
buildOpenRouterApiBaseCandidates,
|
|
1733
1588
|
buildSiliconFlowApiBaseCandidates,
|
|
1734
|
-
buildNewCliWebBaseCandidates,
|
|
1735
1589
|
build88CodeUsageSnapshot,
|
|
1736
1590
|
build88CodeSubscriptionSnapshot,
|
|
1737
|
-
buildNewCliDashboardSnapshot,
|
|
1738
1591
|
buildBalanceProbeStrategies,
|
|
1739
1592
|
getEnabledBalanceChannels,
|
|
1740
1593
|
runBalanceStrategy,
|