kingkont 0.7.37 → 0.7.39
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/index.html +43 -31
- package/package.json +1 -1
- package/server.js +50 -1
- package/settings.html +5 -0
- package/updates.html +5 -0
package/index.html
CHANGED
|
@@ -141,8 +141,20 @@
|
|
|
141
141
|
scroll-snap-type: x proximity;
|
|
142
142
|
}
|
|
143
143
|
.welcome-recent-grid::-webkit-scrollbar { height: 8px; }
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
|
|
145
|
+
/* === Глобальные dark-scrollbars === */
|
|
146
|
+
/* Firefox */
|
|
147
|
+
* { scrollbar-color: #3a3a3a #1a1a1a; scrollbar-width: thin; }
|
|
148
|
+
/* WebKit (Electron/Chrome) — все scroll-области в приложении. */
|
|
149
|
+
::-webkit-scrollbar { width: 10px; height: 10px; background: #1a1a1a; }
|
|
150
|
+
::-webkit-scrollbar-track { background: #1a1a1a; }
|
|
151
|
+
::-webkit-scrollbar-thumb {
|
|
152
|
+
background: #3a3a3a;
|
|
153
|
+
border-radius: 4px;
|
|
154
|
+
border: 2px solid #1a1a1a; /* gap, чтобы thumb «не прилипал» к краям */
|
|
155
|
+
}
|
|
156
|
+
::-webkit-scrollbar-thumb:hover { background: #4a4a4a; }
|
|
157
|
+
::-webkit-scrollbar-corner { background: #1a1a1a; }
|
|
146
158
|
.welcome-card {
|
|
147
159
|
background: #232323; border: 1px solid #333; border-radius: 8px;
|
|
148
160
|
overflow: hidden; cursor: pointer; transition: border-color 0.12s, transform 0.12s;
|
|
@@ -1025,10 +1037,7 @@
|
|
|
1025
1037
|
<div class="sidebar-list" id="episodeList"></div>
|
|
1026
1038
|
</div>
|
|
1027
1039
|
<div class="sidebar-footer">
|
|
1028
|
-
<
|
|
1029
|
-
<span class="dot"></span>
|
|
1030
|
-
<span id="balanceValue">— credits</span>
|
|
1031
|
-
</span>
|
|
1040
|
+
<div id="balancesAll" style="display:flex; flex-direction:column; gap:4px;"></div>
|
|
1032
1041
|
<span id="jobsInfo" class="jobs-info" style="display:none;"></span>
|
|
1033
1042
|
<span class="hint">Перетаскивай файлы на холст · @имя для ссылок</span>
|
|
1034
1043
|
</div>
|
|
@@ -2104,32 +2113,35 @@ window.addEventListener('DOMContentLoaded', async () => {
|
|
|
2104
2113
|
// red (≤0). Также экспортирована глобально как window.refreshBalance —
|
|
2105
2114
|
// чтобы settings-окно могло триггерить обновление после login/logout.
|
|
2106
2115
|
async function refreshBalance() {
|
|
2107
|
-
const
|
|
2108
|
-
|
|
2109
|
-
|
|
2116
|
+
const wrap = document.getElementById('balancesAll');
|
|
2117
|
+
if (!wrap) return;
|
|
2118
|
+
let data = {};
|
|
2110
2119
|
try {
|
|
2111
|
-
const
|
|
2112
|
-
if (
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
const d =
|
|
2124
|
-
|
|
2125
|
-
pill
|
|
2126
|
-
pill.
|
|
2127
|
-
pill.
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
pill.
|
|
2131
|
-
|
|
2132
|
-
|
|
2120
|
+
const r = await fetch('/api/balance/all');
|
|
2121
|
+
if (r.ok) data = await r.json();
|
|
2122
|
+
} catch {}
|
|
2123
|
+
wrap.innerHTML = '';
|
|
2124
|
+
// Один pill на провайдер. Если у провайдера нет данных (выключен или
|
|
2125
|
+
// API не дал баланс) — pill не рендерим.
|
|
2126
|
+
const pills = [
|
|
2127
|
+
{ key: 'kingkont', label: 'KingKont', onClick: () => window.openTxLog?.(), low: 100, fmt: (a) => `<b>${a.toLocaleString('ru-RU')}</b> credits` },
|
|
2128
|
+
{ key: 'openrouter', label: 'OpenRouter', low: 0.5, fmt: (a) => `<b>$${a.toFixed(2)}</b>` },
|
|
2129
|
+
{ key: 'elevenlabs', label: 'ElevenLabs', low: 1000, fmt: (a) => `<b>${a.toLocaleString('ru-RU')}</b> chars` },
|
|
2130
|
+
];
|
|
2131
|
+
for (const p of pills) {
|
|
2132
|
+
const d = data[p.key];
|
|
2133
|
+
if (!d || typeof d.amount !== 'number') continue;
|
|
2134
|
+
const pill = document.createElement('span');
|
|
2135
|
+
pill.className = 'balance-info';
|
|
2136
|
+
pill.title = `Баланс ${p.label}` + (p.onClick ? ' · клик — лог списаний' : '');
|
|
2137
|
+
if (d.amount > 0 && d.amount < (p.low || 0)) pill.classList.add('low');
|
|
2138
|
+
if (d.amount <= 0) pill.classList.add('empty');
|
|
2139
|
+
pill.innerHTML = `<span class="dot"></span><span style="color:#888;font-size:10px;margin-right:4px;">${p.label}</span><span>${p.fmt(d.amount)}</span>`;
|
|
2140
|
+
if (p.onClick) {
|
|
2141
|
+
pill.style.cursor = 'pointer';
|
|
2142
|
+
pill.addEventListener('click', p.onClick);
|
|
2143
|
+
}
|
|
2144
|
+
wrap.appendChild(pill);
|
|
2133
2145
|
}
|
|
2134
2146
|
}
|
|
2135
2147
|
window.refreshBalance = refreshBalance;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kingkont",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.39",
|
|
4
4
|
"description": "KingKont \u00b7 Chatium \u2014 \u043d\u043e\u0434-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0441\u0446\u0435\u043d \u0441 AI-\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 (\u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438/\u0432\u0438\u0434\u0435\u043e/\u0433\u043e\u043b\u043e\u0441/SFX/\u043c\u0443\u0437\u044b\u043a\u0430/\u0442\u0435\u043a\u0441\u0442)",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"bin": {
|
package/server.js
CHANGED
|
@@ -657,7 +657,7 @@ async function handleTransactions(req, res) {
|
|
|
657
657
|
}
|
|
658
658
|
}
|
|
659
659
|
|
|
660
|
-
// ---------- /api/balance (
|
|
660
|
+
// ---------- /api/balance (KingKont — legacy single-balance endpoint) ----------
|
|
661
661
|
async function handleBalance(req, res) {
|
|
662
662
|
const s = getSettings();
|
|
663
663
|
if (!s.useChatium || !s.chatium?.token || !s.chatium?.base) {
|
|
@@ -682,6 +682,54 @@ async function handleBalance(req, res) {
|
|
|
682
682
|
}
|
|
683
683
|
}
|
|
684
684
|
|
|
685
|
+
// ---------- /api/balance/all (агрегированные балансы всех включённых провайдеров) ----------
|
|
686
|
+
async function handleBalanceAll(req, res) {
|
|
687
|
+
const s = getSettings();
|
|
688
|
+
const out = {};
|
|
689
|
+
// KingKont — credits.
|
|
690
|
+
if (s.useChatium && s.chatium?.token && s.chatium?.base) {
|
|
691
|
+
try {
|
|
692
|
+
const url = s.chatium.base.replace(/\/$/, '') + CHATIUM_PATHS.balance;
|
|
693
|
+
const r = await fetch(url, { headers: { 'Authorization': `Bearer ${s.chatium.token}` } });
|
|
694
|
+
const d = await r.json().catch(() => ({}));
|
|
695
|
+
if (r.ok && typeof d.balance === 'number') out.kingkont = { unit: 'credits', amount: d.balance };
|
|
696
|
+
} catch {}
|
|
697
|
+
}
|
|
698
|
+
// ElevenLabs — characters_left = limit - used.
|
|
699
|
+
if (s.useElevenlabs && process.env.ELEVENLABS_API_KEY) {
|
|
700
|
+
try {
|
|
701
|
+
const r = await fetch(`${ELEVEN_BASE}/v1/user/subscription`, {
|
|
702
|
+
headers: { 'xi-api-key': process.env.ELEVENLABS_API_KEY },
|
|
703
|
+
});
|
|
704
|
+
const d = await r.json().catch(() => ({}));
|
|
705
|
+
if (r.ok && typeof d.character_count === 'number' && typeof d.character_limit === 'number') {
|
|
706
|
+
out.elevenlabs = {
|
|
707
|
+
unit: 'chars',
|
|
708
|
+
amount: Math.max(0, d.character_limit - d.character_count),
|
|
709
|
+
limit: d.character_limit,
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
} catch {}
|
|
713
|
+
}
|
|
714
|
+
// OpenRouter — credits в USD.
|
|
715
|
+
if (s.useOpenrouter && process.env.OPENROUTER_API_KEY) {
|
|
716
|
+
try {
|
|
717
|
+
const r = await fetch('https://openrouter.ai/api/v1/credits', {
|
|
718
|
+
headers: { 'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}` },
|
|
719
|
+
});
|
|
720
|
+
const d = await r.json().catch(() => ({}));
|
|
721
|
+
if (r.ok && d.data && typeof d.data.total_credits === 'number') {
|
|
722
|
+
out.openrouter = {
|
|
723
|
+
unit: 'usd',
|
|
724
|
+
amount: Math.max(0, (d.data.total_credits || 0) - (d.data.total_usage || 0)),
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
} catch {}
|
|
728
|
+
}
|
|
729
|
+
// KIE — нет публичного balance-endpoint в их API; пропускаем.
|
|
730
|
+
send(res, 200, out);
|
|
731
|
+
}
|
|
732
|
+
|
|
685
733
|
// ---------- /api/sfx (Chatium ИЛИ ElevenLabs Sound Effects) ----------
|
|
686
734
|
async function handleSfx(req, res) {
|
|
687
735
|
const { text, durationSeconds, promptInfluence = 0.3 } = await readJson(req);
|
|
@@ -885,6 +933,7 @@ const server = createServer(async (req, res) => {
|
|
|
885
933
|
if (req.method === 'POST' && url.pathname === '/api/music') return handleMusic(req, res);
|
|
886
934
|
if (req.method === 'POST' && url.pathname === '/api/text') return handleText(req, res);
|
|
887
935
|
if (req.method === 'GET' && url.pathname === '/api/balance') return handleBalance(req, res);
|
|
936
|
+
if (req.method === 'GET' && url.pathname === '/api/balance/all') return handleBalanceAll(req, res);
|
|
888
937
|
if (req.method === 'GET' && url.pathname === '/api/transactions') return handleTransactions(req, res);
|
|
889
938
|
if (req.method === 'GET') return serveStatic(res, url);
|
|
890
939
|
send(res, 404, 'not found');
|
package/settings.html
CHANGED
|
@@ -105,6 +105,11 @@
|
|
|
105
105
|
|
|
106
106
|
.saved { color: var(--ok); font-size: 12px; opacity: 0; transition: opacity 0.3s; }
|
|
107
107
|
.saved.show { opacity: 1; }
|
|
108
|
+
/* Dark scrollbars — same palette как в основном окне. */
|
|
109
|
+
* { scrollbar-color: #3a3a3a var(--bg); scrollbar-width: thin; }
|
|
110
|
+
::-webkit-scrollbar { width: 10px; height: 10px; background: var(--bg); }
|
|
111
|
+
::-webkit-scrollbar-thumb { background: #3a3a3a; border-radius: 4px; border: 2px solid var(--bg); }
|
|
112
|
+
::-webkit-scrollbar-thumb:hover { background: #4a4a4a; }
|
|
108
113
|
</style>
|
|
109
114
|
</head>
|
|
110
115
|
<body>
|
package/updates.html
CHANGED
|
@@ -74,6 +74,11 @@
|
|
|
74
74
|
0%, 100% { box-shadow: 0 0 0 0 rgba(22,163,74,0.55); }
|
|
75
75
|
50% { box-shadow: 0 0 0 8px rgba(22,163,74,0); }
|
|
76
76
|
}
|
|
77
|
+
/* Dark scrollbars — same palette как в основном окне. */
|
|
78
|
+
* { scrollbar-color: #3a3a3a var(--bg); scrollbar-width: thin; }
|
|
79
|
+
::-webkit-scrollbar { width: 10px; height: 10px; background: var(--bg); }
|
|
80
|
+
::-webkit-scrollbar-thumb { background: #3a3a3a; border-radius: 4px; border: 2px solid var(--bg); }
|
|
81
|
+
::-webkit-scrollbar-thumb:hover { background: #4a4a4a; }
|
|
77
82
|
</style>
|
|
78
83
|
</head>
|
|
79
84
|
<body>
|