coding-tool-x 3.6.6 → 3.6.8
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/CHANGELOG.md +7 -0
- package/dist/web/assets/{Analytics-CcGKjDkP.js → Analytics-C57ZRDq5.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-DPOa1w5D.js → ConfigTemplates-B3qqqL05.js} +1 -1
- package/dist/web/assets/Home-CG5XrTNc.js +1 -0
- package/dist/web/assets/Home-CIua-b-o.css +1 -0
- package/dist/web/assets/{PluginManager-BVbHUdey.js → PluginManager-BhX0LUzr.js} +1 -1
- package/dist/web/assets/{ProjectList-BQrz2FKo.js → ProjectList-BQ01OZn9.js} +1 -1
- package/dist/web/assets/{SessionList-CRGer64T.js → SessionList-DPv2IOXG.js} +1 -1
- package/dist/web/assets/{SkillManager-BhJKtWYM.js → SkillManager-D5CfQm2O.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-pc6tpF3m.js → WorkspaceManager-Ce8ggteK.js} +1 -1
- package/dist/web/assets/index-CpnFNWqC.js +2 -0
- package/dist/web/assets/index-DJ9VFidd.css +1 -0
- package/dist/web/assets/{naive-ui-DM897mIP.js → naive-ui-kcWDeJwl.js} +1 -1
- package/dist/web/index.html +3 -3
- package/package.json +1 -1
- package/src/commands/stats.js +1 -1
- package/src/config/channel-preset-websites.js +2 -1
- package/src/config/paths.js +8 -0
- package/src/server/api/agents.js +16 -54
- package/src/server/api/claude-hooks.js +1 -1
- package/src/server/api/claude-statistics.js +57 -0
- package/src/server/api/commands.js +16 -54
- package/src/server/api/dashboard.js +2 -2
- package/src/server/api/gemini-channels.js +2 -0
- package/src/server/api/hooks.js +4 -1
- package/src/server/api/plugins.js +40 -65
- package/src/server/api/skills.js +21 -77
- package/src/server/api/validation-errors.js +34 -0
- package/src/server/gemini-proxy-server.js +205 -21
- package/src/server/index.js +1 -0
- package/src/server/services/agents-service.js +166 -75
- package/src/server/services/base/base-channel-service.js +15 -0
- package/src/server/services/base/proxy-utils.js +6 -3
- package/src/server/services/base/response-usage-parser.js +44 -0
- package/src/server/services/channel-balance.js +86 -1
- package/src/server/services/claude-statistics-service.js +139 -0
- package/src/server/services/commands-service.js +203 -121
- package/src/server/services/config-artifact-paths.js +116 -0
- package/src/server/services/config-export-service.js +7 -6
- package/src/server/services/config-registry-service.js +2 -2
- package/src/server/services/config-sync-manager.js +45 -11
- package/src/server/services/config-templates-service.js +21 -19
- package/src/server/services/format-converter.js +42 -4
- package/src/server/services/gemini-channels.js +30 -1
- package/src/server/services/gemini-sessions.js +347 -61
- package/src/server/services/mcp-client.js +236 -49
- package/src/server/services/mcp-service.js +51 -64
- package/src/server/services/notification-hooks.js +659 -88
- package/src/server/services/opencode-channels.js +15 -0
- package/src/server/services/plugins-service.js +771 -63
- package/src/server/services/repo-scanner-base.js +6 -29
- package/src/server/services/skill-service.js +187 -63
- package/dist/web/assets/Home-BP1LxGtp.js +0 -1
- package/dist/web/assets/Home-BeGkC4bb.css +0 -1
- package/dist/web/assets/index-0isNzXNY.css +0 -1
- package/dist/web/assets/index-BsdIJwLf.js +0 -2
|
@@ -80,6 +80,19 @@ function forgetBalanceStrategy(key) {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
function isRememberedHiddenStrategy(strategy) {
|
|
84
|
+
return strategy?.type === 'unsupported-balance'
|
|
85
|
+
|| strategy?.type === 'unavailable-balance';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function makeUnavailableBalanceStrategy(snapshot = {}, baseUrl = '') {
|
|
89
|
+
return {
|
|
90
|
+
type: 'unavailable-balance',
|
|
91
|
+
platform: snapshot.platform || null,
|
|
92
|
+
baseUrl: normalizeBaseUrl(baseUrl) || baseUrl || null
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
83
96
|
function nowIso(now = Date.now()) {
|
|
84
97
|
return new Date(now).toISOString();
|
|
85
98
|
}
|
|
@@ -1270,6 +1283,12 @@ async function runBalanceStrategy(strategy, token, channel = {}) {
|
|
|
1270
1283
|
strategy
|
|
1271
1284
|
};
|
|
1272
1285
|
}
|
|
1286
|
+
if (strategy.type === 'unavailable-balance') {
|
|
1287
|
+
return {
|
|
1288
|
+
snapshot: makeHiddenSnapshot(strategy.platform || null),
|
|
1289
|
+
strategy
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1273
1292
|
if (strategy.type === 'siliconflow-user-info') {
|
|
1274
1293
|
return {
|
|
1275
1294
|
snapshot: await runSiliconFlowUserInfoStrategy(strategy, token),
|
|
@@ -1292,6 +1311,7 @@ async function tryBalanceStrategy(strategy, token, channel = {}) {
|
|
|
1292
1311
|
|
|
1293
1312
|
async function probeBalanceFromBase(baseUrl, channel, token) {
|
|
1294
1313
|
let lastSnapshot = null;
|
|
1314
|
+
let lastHiddenStrategy = null;
|
|
1295
1315
|
for (const strategy of buildBalanceProbeStrategies(baseUrl, channel, token)) {
|
|
1296
1316
|
const result = await tryBalanceStrategy(strategy, token, channel);
|
|
1297
1317
|
if (result) return result;
|
|
@@ -1304,8 +1324,11 @@ async function probeBalanceFromBase(baseUrl, channel, token) {
|
|
|
1304
1324
|
: strategy.platform || null
|
|
1305
1325
|
);
|
|
1306
1326
|
}
|
|
1327
|
+
if (isRememberedHiddenStrategy(strategy)) {
|
|
1328
|
+
lastHiddenStrategy = strategy;
|
|
1329
|
+
}
|
|
1307
1330
|
}
|
|
1308
|
-
return lastSnapshot ? { snapshot: lastSnapshot, strategy:
|
|
1331
|
+
return lastSnapshot ? { snapshot: lastSnapshot, strategy: lastHiddenStrategy } : null;
|
|
1309
1332
|
}
|
|
1310
1333
|
|
|
1311
1334
|
function buildCacheKey(source, channel) {
|
|
@@ -1341,6 +1364,27 @@ async function refreshChannelBalanceSnapshot(source, channel, options = {}) {
|
|
|
1341
1364
|
loadPersistedStrategyCache();
|
|
1342
1365
|
const cachedStrategy = balanceStrategyCache.get(key);
|
|
1343
1366
|
if (cachedStrategy) {
|
|
1367
|
+
if (isRememberedHiddenStrategy(cachedStrategy)) {
|
|
1368
|
+
const strategyResult = await runBalanceStrategy(cachedStrategy, token, channel);
|
|
1369
|
+
const hiddenSnapshot = strategyResult?.snapshot || makeHiddenSnapshot(cachedStrategy.platform || null);
|
|
1370
|
+
if (cached?.snapshot?.visible) {
|
|
1371
|
+
const staleSnapshot = {
|
|
1372
|
+
...cached.snapshot,
|
|
1373
|
+
stale: true
|
|
1374
|
+
};
|
|
1375
|
+
balanceCache.set(key, {
|
|
1376
|
+
snapshot: staleSnapshot,
|
|
1377
|
+
expiresAt: currentTime + CACHE_TTL_MS
|
|
1378
|
+
});
|
|
1379
|
+
return staleSnapshot;
|
|
1380
|
+
}
|
|
1381
|
+
balanceCache.set(key, {
|
|
1382
|
+
snapshot: hiddenSnapshot,
|
|
1383
|
+
expiresAt: currentTime + CACHE_TTL_MS
|
|
1384
|
+
});
|
|
1385
|
+
return hiddenSnapshot;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1344
1388
|
const strategyResult = await tryBalanceStrategy(cachedStrategy, token, channel);
|
|
1345
1389
|
if (strategyResult?.snapshot?.visible) {
|
|
1346
1390
|
rememberBalanceStrategy(key, strategyResult.strategy);
|
|
@@ -1366,6 +1410,13 @@ async function refreshChannelBalanceSnapshot(source, channel, options = {}) {
|
|
|
1366
1410
|
lastSnapshot = result?.snapshot || makeHiddenSnapshot(null, { updatedAt: nowIso(currentTime) });
|
|
1367
1411
|
}
|
|
1368
1412
|
|
|
1413
|
+
const hiddenStrategy = lastSnapshot
|
|
1414
|
+
? makeUnavailableBalanceStrategy(lastSnapshot, bases[0])
|
|
1415
|
+
: null;
|
|
1416
|
+
if (hiddenStrategy) {
|
|
1417
|
+
rememberBalanceStrategy(key, hiddenStrategy);
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1369
1420
|
if (cached?.snapshot?.visible) {
|
|
1370
1421
|
const staleSnapshot = {
|
|
1371
1422
|
...cached.snapshot,
|
|
@@ -1381,6 +1432,38 @@ async function refreshChannelBalanceSnapshot(source, channel, options = {}) {
|
|
|
1381
1432
|
return lastSnapshot || makeHiddenSnapshot(null, { updatedAt: nowIso(currentTime) });
|
|
1382
1433
|
}
|
|
1383
1434
|
|
|
1435
|
+
function clearChannelBalanceCache(source, channel) {
|
|
1436
|
+
const normalizedSource = validateSource(source);
|
|
1437
|
+
if (!channel) return;
|
|
1438
|
+
loadPersistedStrategyCache();
|
|
1439
|
+
|
|
1440
|
+
const exactKey = buildCacheKey(normalizedSource, channel);
|
|
1441
|
+
const identity = channel.id || channel.name || 'unknown';
|
|
1442
|
+
const prefix = `${normalizedSource}:${identity}:`;
|
|
1443
|
+
let strategyChanged = false;
|
|
1444
|
+
|
|
1445
|
+
balanceCache.delete(exactKey);
|
|
1446
|
+
for (const key of Array.from(balanceCache.keys())) {
|
|
1447
|
+
if (key.startsWith(prefix)) {
|
|
1448
|
+
balanceCache.delete(key);
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
if (balanceStrategyCache.delete(exactKey)) {
|
|
1453
|
+
strategyChanged = true;
|
|
1454
|
+
}
|
|
1455
|
+
for (const key of Array.from(balanceStrategyCache.keys())) {
|
|
1456
|
+
if (key.startsWith(prefix)) {
|
|
1457
|
+
balanceStrategyCache.delete(key);
|
|
1458
|
+
strategyChanged = true;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
if (strategyChanged) {
|
|
1463
|
+
writePersistedStrategyCache();
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1384
1467
|
function getChannelsForSource(source) {
|
|
1385
1468
|
if (source === 'claude') {
|
|
1386
1469
|
return require('./channels').getAllChannels() || [];
|
|
@@ -1482,8 +1565,10 @@ function clearBalanceCache() {
|
|
|
1482
1565
|
module.exports = {
|
|
1483
1566
|
getChannelBalances,
|
|
1484
1567
|
refreshChannelBalance,
|
|
1568
|
+
clearChannelBalanceCache,
|
|
1485
1569
|
_test: {
|
|
1486
1570
|
clearBalanceCache,
|
|
1571
|
+
clearChannelBalanceCache,
|
|
1487
1572
|
normalizeBaseUrl,
|
|
1488
1573
|
buildBaseCandidates,
|
|
1489
1574
|
buildHubBalanceSnapshot,
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
const {
|
|
2
|
+
recordRequest: recordSharedRequest,
|
|
3
|
+
getStatistics: getSharedStatistics,
|
|
4
|
+
getDailyStatistics: getSharedDailyStatistics,
|
|
5
|
+
getTodayStatistics: getSharedTodayStatistics
|
|
6
|
+
} = require('./statistics-service');
|
|
7
|
+
const { normalizeUsageTokens, toNumber } = require('./proxy-log-helper');
|
|
8
|
+
|
|
9
|
+
const TOOL_TYPE = 'claude-code';
|
|
10
|
+
const USAGE_SOURCE = 'claude';
|
|
11
|
+
|
|
12
|
+
function toLegacyEntryShape(entry = {}, includeName = false) {
|
|
13
|
+
const normalized = normalizeUsageTokens(USAGE_SOURCE, entry.tokens || {});
|
|
14
|
+
const result = {
|
|
15
|
+
requests: toNumber(entry.requests),
|
|
16
|
+
tokens: {
|
|
17
|
+
input: normalized.input,
|
|
18
|
+
output: normalized.output,
|
|
19
|
+
cacheCreation: normalized.cacheCreation,
|
|
20
|
+
cacheRead: normalized.cacheRead,
|
|
21
|
+
cached: normalized.cached,
|
|
22
|
+
total: normalized.total
|
|
23
|
+
},
|
|
24
|
+
cost: toNumber(entry.cost)
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
if (includeName) {
|
|
28
|
+
result.name = entry.name || '';
|
|
29
|
+
if (entry.firstUsed) result.firstUsed = entry.firstUsed;
|
|
30
|
+
if (entry.lastUsed) result.lastUsed = entry.lastUsed;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function pickToolScope(sharedStats = {}) {
|
|
37
|
+
const byToolType = sharedStats.byToolType || {};
|
|
38
|
+
const toolScope = byToolType[TOOL_TYPE] || {};
|
|
39
|
+
|
|
40
|
+
let byChannel = {};
|
|
41
|
+
let byModel = {};
|
|
42
|
+
|
|
43
|
+
if (toolScope.channels && typeof toolScope.channels === 'object') {
|
|
44
|
+
byChannel = toolScope.channels;
|
|
45
|
+
} else {
|
|
46
|
+
byChannel = Object.fromEntries(
|
|
47
|
+
Object.entries(sharedStats.byChannel || {}).filter(([, value]) => value?.toolType === TOOL_TYPE)
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (toolScope.models && typeof toolScope.models === 'object') {
|
|
52
|
+
byModel = toolScope.models;
|
|
53
|
+
} else {
|
|
54
|
+
byModel = Object.fromEntries(
|
|
55
|
+
Object.entries(sharedStats.byModel || {}).filter(([, value]) => value?.toolType === TOOL_TYPE)
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return { toolScope, byChannel, byModel };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function buildSummaryStatistics(sharedStats = {}) {
|
|
63
|
+
const { toolScope, byChannel, byModel } = pickToolScope(sharedStats);
|
|
64
|
+
const normalized = toLegacyEntryShape(toolScope);
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
version: '1.0',
|
|
68
|
+
lastUpdated: sharedStats.lastUpdated || new Date().toISOString(),
|
|
69
|
+
global: {
|
|
70
|
+
totalRequests: normalized.requests,
|
|
71
|
+
totalTokens: normalized.tokens.total,
|
|
72
|
+
totalCost: normalized.cost
|
|
73
|
+
},
|
|
74
|
+
byChannel: Object.fromEntries(
|
|
75
|
+
Object.entries(byChannel).map(([key, value]) => [key, toLegacyEntryShape(value, true)])
|
|
76
|
+
),
|
|
77
|
+
byModel: Object.fromEntries(
|
|
78
|
+
Object.entries(byModel).map(([key, value]) => [key, toLegacyEntryShape(value)])
|
|
79
|
+
)
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function buildDailyStatistics(sharedDaily = {}, fallbackDate) {
|
|
84
|
+
const { byToolType = {} } = sharedDaily;
|
|
85
|
+
const toolScope = byToolType[TOOL_TYPE] || {};
|
|
86
|
+
const normalized = toLegacyEntryShape(toolScope);
|
|
87
|
+
const byChannel = toolScope.channels || {};
|
|
88
|
+
const byModel = toolScope.models || {};
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
date: sharedDaily.date || fallbackDate,
|
|
92
|
+
summary: {
|
|
93
|
+
requests: normalized.requests,
|
|
94
|
+
tokens: normalized.tokens.total,
|
|
95
|
+
cost: normalized.cost
|
|
96
|
+
},
|
|
97
|
+
byChannel: Object.fromEntries(
|
|
98
|
+
Object.entries(byChannel).map(([key, value]) => [key, toLegacyEntryShape(value, true)])
|
|
99
|
+
),
|
|
100
|
+
byModel: Object.fromEntries(
|
|
101
|
+
Object.entries(byModel).map(([key, value]) => [key, toLegacyEntryShape(value)])
|
|
102
|
+
)
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function recordRequest(requestData = {}) {
|
|
107
|
+
const normalizedTokens = normalizeUsageTokens(USAGE_SOURCE, requestData.tokens || {});
|
|
108
|
+
return recordSharedRequest({
|
|
109
|
+
...requestData,
|
|
110
|
+
toolType: TOOL_TYPE,
|
|
111
|
+
tokens: {
|
|
112
|
+
input: normalizedTokens.input,
|
|
113
|
+
output: normalizedTokens.output,
|
|
114
|
+
cached: normalizedTokens.cached,
|
|
115
|
+
cacheCreation: normalizedTokens.cacheCreation,
|
|
116
|
+
cacheRead: normalizedTokens.cacheRead,
|
|
117
|
+
total: normalizedTokens.total
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function getStatistics() {
|
|
123
|
+
return buildSummaryStatistics(getSharedStatistics());
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function getDailyStatistics(date) {
|
|
127
|
+
return buildDailyStatistics(getSharedDailyStatistics(date), date);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function getTodayStatistics() {
|
|
131
|
+
return buildDailyStatistics(getSharedTodayStatistics());
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
module.exports = {
|
|
135
|
+
recordRequest,
|
|
136
|
+
getStatistics,
|
|
137
|
+
getDailyStatistics,
|
|
138
|
+
getTodayStatistics
|
|
139
|
+
};
|