@polderlabs/bizar 4.4.10 → 4.4.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/bizar-dash/dist/assets/{main-Nq8Dq3VR.css → main-BKXEqU1w.css} +1 -1
- package/bizar-dash/dist/assets/main-EK_fzXn_.js +352 -0
- package/bizar-dash/dist/assets/main-EK_fzXn_.js.map +1 -0
- package/bizar-dash/dist/assets/mobile-Dl1q7Cyq.js.map +1 -1
- package/bizar-dash/dist/index.html +2 -2
- package/bizar-dash/src/server/api.mjs +2 -0
- package/bizar-dash/src/server/minimax.mjs +352 -0
- package/bizar-dash/src/server/mods-loader.mjs +169 -1
- package/bizar-dash/src/server/routes/_shared.mjs +15 -0
- package/bizar-dash/src/server/routes/minimax.mjs +140 -0
- package/bizar-dash/src/web/App.tsx +2 -0
- package/bizar-dash/src/web/components/Topbar.tsx +2 -0
- package/bizar-dash/src/web/lib/types.ts +12 -0
- package/bizar-dash/src/web/main.tsx +1 -0
- package/bizar-dash/src/web/styles/minimax-usage.css +371 -0
- package/bizar-dash/src/web/views/MiniMaxUsage.tsx +543 -0
- package/cli/bin.mjs +39 -6
- package/cli/provision.mjs +182 -2
- package/package.json +1 -1
- package/bizar-dash/dist/assets/main-CEazNxxy.js +0 -347
- package/bizar-dash/dist/assets/main-CEazNxxy.js.map +0 -1
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/server/routes/minimax.mjs
|
|
3
|
+
*
|
|
4
|
+
* v4.5.0 — REST surface for the MiniMax Token Plan integration.
|
|
5
|
+
*
|
|
6
|
+
* Endpoints:
|
|
7
|
+
* GET /api/minimax/status — current key + cached remains summary
|
|
8
|
+
* GET /api/minimax/remains — full remains snapshot (5h + weekly per model)
|
|
9
|
+
* POST /api/minimax/remains/refresh — force re-fetch from the API
|
|
10
|
+
* POST /api/minimax/test — smoke-test the key with a one-shot chat call
|
|
11
|
+
* GET /api/minimax/cache — read the on-disk cache file (for debugging)
|
|
12
|
+
*
|
|
13
|
+
* All endpoints read the API key from settings.json (no key is ever
|
|
14
|
+
* accepted as a URL param or body field — the user puts it in the
|
|
15
|
+
* settings UI). Responses never echo the key back; they include a
|
|
16
|
+
* masked `apiKeyHint` (last 4 chars only).
|
|
17
|
+
*/
|
|
18
|
+
import { Router } from 'express';
|
|
19
|
+
import {
|
|
20
|
+
fetchRemains,
|
|
21
|
+
chatCompletion,
|
|
22
|
+
readCachedRemains,
|
|
23
|
+
clearRemainsCache,
|
|
24
|
+
readMinimaxSettings,
|
|
25
|
+
maskKey,
|
|
26
|
+
KNOWN_MODELS,
|
|
27
|
+
} from '../minimax.mjs';
|
|
28
|
+
import { wrap } from './_shared.mjs';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {object} deps
|
|
32
|
+
* @param {object} deps.state
|
|
33
|
+
* @param {Function} deps.broadcast
|
|
34
|
+
* @returns {import('express').Router}
|
|
35
|
+
*/
|
|
36
|
+
export function createMinimaxRouter({ state, broadcast }) {
|
|
37
|
+
const router = Router();
|
|
38
|
+
|
|
39
|
+
// GET / — health + config summary
|
|
40
|
+
router.get('/minimax/status', wrap(async (_req, res) => {
|
|
41
|
+
const settings = readMinimaxSettings();
|
|
42
|
+
const cached = readCachedRemains();
|
|
43
|
+
res.json({
|
|
44
|
+
enabled: settings.enabled,
|
|
45
|
+
configured: !!settings.apiKey,
|
|
46
|
+
apiKeyHint: maskKey(settings.apiKey),
|
|
47
|
+
groupId: settings.groupId,
|
|
48
|
+
baseUrl: settings.baseUrl,
|
|
49
|
+
chatBaseUrl: settings.chatBaseUrl,
|
|
50
|
+
knownModels: KNOWN_MODELS,
|
|
51
|
+
cache: cached
|
|
52
|
+
? {
|
|
53
|
+
fetchedAt: cached.fetchedAt,
|
|
54
|
+
apiKeyHint: cached.apiKeyHint,
|
|
55
|
+
groupId: cached.groupId,
|
|
56
|
+
modelCount: (cached.models || []).length,
|
|
57
|
+
}
|
|
58
|
+
: null,
|
|
59
|
+
});
|
|
60
|
+
}));
|
|
61
|
+
|
|
62
|
+
// GET /remains — current snapshot (cache-or-fetch)
|
|
63
|
+
router.get('/minimax/remains', wrap(async (_req, res) => {
|
|
64
|
+
const settings = readMinimaxSettings();
|
|
65
|
+
if (!settings.enabled) {
|
|
66
|
+
res.json({ ok: false, error: 'disabled', message: 'MiniMax integration is disabled in settings' });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const result = await fetchRemains({
|
|
70
|
+
apiKey: settings.apiKey,
|
|
71
|
+
groupId: settings.groupId,
|
|
72
|
+
baseUrl: settings.baseUrl,
|
|
73
|
+
});
|
|
74
|
+
if (broadcast && result.ok) {
|
|
75
|
+
broadcast({ type: 'minimax:remains', remains: result });
|
|
76
|
+
}
|
|
77
|
+
res.json(result);
|
|
78
|
+
}));
|
|
79
|
+
|
|
80
|
+
// POST /remains/refresh — force re-fetch (bypass cache TTL)
|
|
81
|
+
router.post('/minimax/remains/refresh', wrap(async (_req, res) => {
|
|
82
|
+
const settings = readMinimaxSettings();
|
|
83
|
+
if (!settings.enabled) {
|
|
84
|
+
res.json({ ok: false, error: 'disabled', message: 'MiniMax integration is disabled in settings' });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const result = await fetchRemains({
|
|
88
|
+
apiKey: settings.apiKey,
|
|
89
|
+
groupId: settings.groupId,
|
|
90
|
+
baseUrl: settings.baseUrl,
|
|
91
|
+
force: true,
|
|
92
|
+
});
|
|
93
|
+
if (broadcast && result.ok) {
|
|
94
|
+
broadcast({ type: 'minimax:remains:refreshed', remains: result });
|
|
95
|
+
}
|
|
96
|
+
res.json(result);
|
|
97
|
+
}));
|
|
98
|
+
|
|
99
|
+
// POST /test — smoke-test the key with a chat completion
|
|
100
|
+
router.post('/minimax/test', wrap(async (req, res) => {
|
|
101
|
+
const settings = readMinimaxSettings();
|
|
102
|
+
if (!settings.enabled) {
|
|
103
|
+
res.json({ ok: false, error: 'disabled', message: 'MiniMax integration is disabled in settings' });
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (!settings.apiKey) {
|
|
107
|
+
res.json({ ok: false, error: 'no_api_key', message: 'MiniMax API key is not configured' });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const body = req.body || {};
|
|
111
|
+
const prompt = typeof body.prompt === 'string' && body.prompt.trim()
|
|
112
|
+
? body.prompt
|
|
113
|
+
: 'Reply with the single word: ok';
|
|
114
|
+
const model = typeof body.model === 'string' && body.model.trim()
|
|
115
|
+
? body.model.trim()
|
|
116
|
+
: 'MiniMax-M3';
|
|
117
|
+
const result = await chatCompletion({
|
|
118
|
+
apiKey: settings.apiKey,
|
|
119
|
+
prompt,
|
|
120
|
+
model,
|
|
121
|
+
baseUrl: settings.chatBaseUrl,
|
|
122
|
+
maxTokens: typeof body.maxTokens === 'number' ? body.maxTokens : 32,
|
|
123
|
+
});
|
|
124
|
+
res.json(result);
|
|
125
|
+
}));
|
|
126
|
+
|
|
127
|
+
// GET /cache — read the on-disk cache (debugging)
|
|
128
|
+
router.get('/minimax/cache', wrap(async (_req, res) => {
|
|
129
|
+
res.json(readCachedRemains() || null);
|
|
130
|
+
}));
|
|
131
|
+
|
|
132
|
+
// DELETE /cache — clear cache (admin endpoint)
|
|
133
|
+
router.delete('/minimax/cache', wrap(async (_req, res) => {
|
|
134
|
+
clearRemainsCache();
|
|
135
|
+
if (broadcast) broadcast({ type: 'minimax:cache:cleared' });
|
|
136
|
+
res.json({ ok: true });
|
|
137
|
+
}));
|
|
138
|
+
|
|
139
|
+
return router;
|
|
140
|
+
}
|
|
@@ -35,6 +35,7 @@ import { ModView, type ModView as ModViewType } from './views/ModView';
|
|
|
35
35
|
import { Schedules } from './views/Schedules';
|
|
36
36
|
import { Skills } from './views/Skills';
|
|
37
37
|
import { History } from './views/History';
|
|
38
|
+
import { MiniMaxUsage } from './views/MiniMaxUsage';
|
|
38
39
|
import { BackgroundAgents } from './views/BackgroundAgents';
|
|
39
40
|
import { Spinner } from './components/Spinner';
|
|
40
41
|
import { Button } from './components/Button';
|
|
@@ -75,6 +76,7 @@ const VIEW_MAP: Record<string, (p: ViewProps) => React.ReactNode> = {
|
|
|
75
76
|
schedules: Schedules,
|
|
76
77
|
skills: Skills,
|
|
77
78
|
history: History,
|
|
79
|
+
minimax: MiniMaxUsage,
|
|
78
80
|
};
|
|
79
81
|
|
|
80
82
|
const VERSION = 'v3.21.0';
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
Sparkles,
|
|
22
22
|
Activity,
|
|
23
23
|
Radio,
|
|
24
|
+
Coins,
|
|
24
25
|
type LucideIcon,
|
|
25
26
|
} from 'lucide-react';
|
|
26
27
|
import { cn } from '../lib/utils';
|
|
@@ -48,6 +49,7 @@ export const TABS: TabDef[] = [
|
|
|
48
49
|
{ id: 'mods', label: 'Mods', icon: Puzzle },
|
|
49
50
|
{ id: 'schedules', label: 'Schedules', icon: Clock },
|
|
50
51
|
{ id: 'history', label: 'History', icon: HistoryIcon },
|
|
52
|
+
{ id: 'minimax', label: 'Usage', icon: Coins },
|
|
51
53
|
{ id: 'config', label: 'Config', icon: Settings2 },
|
|
52
54
|
{ id: 'settings', label: 'Settings', icon: Sliders },
|
|
53
55
|
];
|
|
@@ -265,6 +265,18 @@ export type Settings = {
|
|
|
265
265
|
};
|
|
266
266
|
// v3.21.0 — System LLM calls (auto-title, enhance-prompt, summarization).
|
|
267
267
|
systemLlm?: SystemLlmConfig;
|
|
268
|
+
// v4.5.0 — MiniMax Token Plan integration. `apiKey` is the user's
|
|
269
|
+
// Subscription Key (NOT a pay-as-you-go API key). `groupId` is usually
|
|
270
|
+
// 'default' for an individual team. `baseUrl` is the Token Plan host
|
|
271
|
+
// (the remains endpoint lives on www.*, not api.*). `chatBaseUrl` is
|
|
272
|
+
// the chat-completions host (api.*/v1).
|
|
273
|
+
minimax?: {
|
|
274
|
+
enabled: boolean;
|
|
275
|
+
apiKey: string;
|
|
276
|
+
groupId: string;
|
|
277
|
+
baseUrl: string;
|
|
278
|
+
chatBaseUrl: string;
|
|
279
|
+
};
|
|
268
280
|
};
|
|
269
281
|
|
|
270
282
|
export type SettingsResponse = {
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* src/web/styles/minimax-usage.css
|
|
3
|
+
*
|
|
4
|
+
* v4.5.0 — Styles for the MiniMax Token Plan usage dashboard.
|
|
5
|
+
*
|
|
6
|
+
* Scope: `.view-minimax-usage` and all child classes prefixed with
|
|
7
|
+
* `minimax-`. Reuses the dashboard's existing CSS variables
|
|
8
|
+
* (--accent, --bg-1, --bg-2, --border, --text, --text-muted, --success,
|
|
9
|
+
* --warning, --error) so the page inherits the rest of the design
|
|
10
|
+
* system automatically.
|
|
11
|
+
* ========================================================================== */
|
|
12
|
+
|
|
13
|
+
.view-minimax-usage {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
gap: 16px;
|
|
17
|
+
padding: 16px 20px 32px;
|
|
18
|
+
max-width: 1280px;
|
|
19
|
+
margin: 0 auto;
|
|
20
|
+
width: 100%;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* ── header ────────────────────────────────────────────────────────────── */
|
|
24
|
+
.view-minimax-usage .view-header {
|
|
25
|
+
display: flex;
|
|
26
|
+
justify-content: space-between;
|
|
27
|
+
align-items: flex-end;
|
|
28
|
+
gap: 16px;
|
|
29
|
+
flex-wrap: wrap;
|
|
30
|
+
}
|
|
31
|
+
.view-minimax-usage .view-header-titles { flex: 1 1 360px; min-width: 0; }
|
|
32
|
+
.view-minimax-usage .view-title {
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
font-size: 22px;
|
|
36
|
+
font-weight: 600;
|
|
37
|
+
margin: 0 0 4px;
|
|
38
|
+
color: var(--text);
|
|
39
|
+
}
|
|
40
|
+
.view-minimax-usage .view-subtitle {
|
|
41
|
+
margin: 0;
|
|
42
|
+
color: var(--text-muted);
|
|
43
|
+
font-size: 13px;
|
|
44
|
+
}
|
|
45
|
+
.view-minimax-usage .view-subtitle code {
|
|
46
|
+
font-size: 12px;
|
|
47
|
+
padding: 1px 5px;
|
|
48
|
+
border-radius: 3px;
|
|
49
|
+
background: var(--bg-2);
|
|
50
|
+
color: var(--text);
|
|
51
|
+
}
|
|
52
|
+
.view-minimax-usage .view-header-actions { display: flex; gap: 8px; align-items: center; }
|
|
53
|
+
|
|
54
|
+
/* ── banner (warn / err) ───────────────────────────────────────────── */
|
|
55
|
+
.view-minimax-usage .banner {
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
gap: 10px;
|
|
59
|
+
padding: 10px 14px;
|
|
60
|
+
border-radius: 8px;
|
|
61
|
+
font-size: 13px;
|
|
62
|
+
border: 1px solid transparent;
|
|
63
|
+
}
|
|
64
|
+
.view-minimax-usage .banner code {
|
|
65
|
+
font-size: 12px;
|
|
66
|
+
padding: 1px 5px;
|
|
67
|
+
border-radius: 3px;
|
|
68
|
+
background: rgba(0,0,0,0.18);
|
|
69
|
+
}
|
|
70
|
+
.view-minimax-usage .banner-warn {
|
|
71
|
+
background: rgba(217, 158, 38, 0.12);
|
|
72
|
+
border-color: rgba(217, 158, 38, 0.35);
|
|
73
|
+
color: var(--text);
|
|
74
|
+
}
|
|
75
|
+
.view-minimax-usage .banner-err {
|
|
76
|
+
background: rgba(248, 81, 73, 0.10);
|
|
77
|
+
border-color: rgba(248, 81, 73, 0.40);
|
|
78
|
+
color: var(--text);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* ── stat row ──────────────────────────────────────────────────────── */
|
|
82
|
+
.view-minimax-usage .minimax-stats-row {
|
|
83
|
+
display: grid;
|
|
84
|
+
grid-template-columns: repeat(4, 1fr);
|
|
85
|
+
gap: 12px;
|
|
86
|
+
}
|
|
87
|
+
@media (max-width: 900px) {
|
|
88
|
+
.view-minimax-usage .minimax-stats-row { grid-template-columns: repeat(2, 1fr); }
|
|
89
|
+
}
|
|
90
|
+
.view-minimax-usage .stat {
|
|
91
|
+
background: var(--bg-1);
|
|
92
|
+
border: 1px solid var(--border);
|
|
93
|
+
border-radius: 8px;
|
|
94
|
+
padding: 12px 14px;
|
|
95
|
+
display: flex;
|
|
96
|
+
flex-direction: column;
|
|
97
|
+
gap: 2px;
|
|
98
|
+
}
|
|
99
|
+
.view-minimax-usage .stat-label {
|
|
100
|
+
font-size: 11px;
|
|
101
|
+
letter-spacing: 0.05em;
|
|
102
|
+
text-transform: uppercase;
|
|
103
|
+
color: var(--text-muted);
|
|
104
|
+
}
|
|
105
|
+
.view-minimax-usage .stat-value {
|
|
106
|
+
font-size: 18px;
|
|
107
|
+
font-weight: 600;
|
|
108
|
+
color: var(--text);
|
|
109
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
110
|
+
word-break: break-word;
|
|
111
|
+
}
|
|
112
|
+
.view-minimax-usage .stat-hint {
|
|
113
|
+
font-size: 11px;
|
|
114
|
+
color: var(--text-muted);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* ── per-model quota grid ────────────────────────────────────────── */
|
|
118
|
+
.view-minimax-usage .minimax-models-grid {
|
|
119
|
+
display: grid;
|
|
120
|
+
grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
|
|
121
|
+
gap: 14px;
|
|
122
|
+
}
|
|
123
|
+
.view-minimax-usage .minimax-model-card { padding: 14px 16px; }
|
|
124
|
+
.view-minimax-usage .minimax-model-head {
|
|
125
|
+
display: flex;
|
|
126
|
+
justify-content: space-between;
|
|
127
|
+
align-items: center;
|
|
128
|
+
margin-bottom: 12px;
|
|
129
|
+
gap: 8px;
|
|
130
|
+
}
|
|
131
|
+
.view-minimax-usage .minimax-model-name {
|
|
132
|
+
font-size: 15px;
|
|
133
|
+
font-weight: 600;
|
|
134
|
+
color: var(--text);
|
|
135
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
136
|
+
}
|
|
137
|
+
.view-minimax-usage .minimax-model-status {
|
|
138
|
+
font-size: 11px;
|
|
139
|
+
color: var(--text-muted);
|
|
140
|
+
text-transform: lowercase;
|
|
141
|
+
letter-spacing: 0.02em;
|
|
142
|
+
}
|
|
143
|
+
.view-minimax-usage .minimax-model-status.is-warn { color: var(--warning, #d29922); }
|
|
144
|
+
.view-minimax-usage .minimax-model-status.is-ok { color: var(--success, #3fb950); }
|
|
145
|
+
|
|
146
|
+
/* ── quota rows inside a model card ─────────────────────────────── */
|
|
147
|
+
.view-minimax-usage .minimax-quota-rows {
|
|
148
|
+
display: flex;
|
|
149
|
+
flex-direction: column;
|
|
150
|
+
gap: 10px;
|
|
151
|
+
}
|
|
152
|
+
.view-minimax-usage .minimax-quota-row {
|
|
153
|
+
display: flex;
|
|
154
|
+
flex-direction: column;
|
|
155
|
+
gap: 4px;
|
|
156
|
+
padding: 8px 10px;
|
|
157
|
+
border-radius: 6px;
|
|
158
|
+
background: rgba(255,255,255,0.02);
|
|
159
|
+
border: 1px solid var(--border);
|
|
160
|
+
}
|
|
161
|
+
.view-minimax-usage .minimax-quota-row.is-good { border-color: rgba(63, 185, 80, 0.25); }
|
|
162
|
+
.view-minimax-usage .minimax-quota-row.is-warn { border-color: rgba(217, 158, 38, 0.35); background: rgba(217, 158, 38, 0.05); }
|
|
163
|
+
.view-minimax-usage .minimax-quota-row.is-low { border-color: rgba(248, 81, 73, 0.45); background: rgba(248, 81, 73, 0.06); }
|
|
164
|
+
|
|
165
|
+
.view-minimax-usage .minimax-quota-head {
|
|
166
|
+
display: flex;
|
|
167
|
+
justify-content: space-between;
|
|
168
|
+
align-items: center;
|
|
169
|
+
font-size: 12px;
|
|
170
|
+
color: var(--text-muted);
|
|
171
|
+
}
|
|
172
|
+
.view-minimax-usage .minimax-quota-label {
|
|
173
|
+
display: inline-flex;
|
|
174
|
+
align-items: center;
|
|
175
|
+
gap: 4px;
|
|
176
|
+
color: var(--text);
|
|
177
|
+
font-weight: 500;
|
|
178
|
+
}
|
|
179
|
+
.view-minimax-usage .minimax-quota-remaining {
|
|
180
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
181
|
+
font-weight: 600;
|
|
182
|
+
color: var(--text);
|
|
183
|
+
}
|
|
184
|
+
.view-minimax-usage .minimax-quota-row.is-good .minimax-quota-remaining { color: var(--success, #3fb950); }
|
|
185
|
+
.view-minimax-usage .minimax-quota-row.is-warn .minimax-quota-remaining { color: var(--warning, #d29922); }
|
|
186
|
+
.view-minimax-usage .minimax-quota-row.is-low .minimax-quota-remaining { color: var(--error, #f85149); }
|
|
187
|
+
|
|
188
|
+
.view-minimax-usage .minimax-bar {
|
|
189
|
+
position: relative;
|
|
190
|
+
height: 8px;
|
|
191
|
+
background: var(--bg-2);
|
|
192
|
+
border-radius: 4px;
|
|
193
|
+
overflow: hidden;
|
|
194
|
+
}
|
|
195
|
+
.view-minimax-usage .minimax-bar-fill {
|
|
196
|
+
height: 100%;
|
|
197
|
+
background: var(--accent);
|
|
198
|
+
transition: width 200ms ease-out;
|
|
199
|
+
}
|
|
200
|
+
.view-minimax-usage .minimax-quota-row.is-good .minimax-bar-fill { background: var(--success, #3fb950); }
|
|
201
|
+
.view-minimax-usage .minimax-quota-row.is-warn .minimax-bar-fill { background: var(--warning, #d29922); }
|
|
202
|
+
.view-minimax-usage .minimax-quota-row.is-low .minimax-bar-fill { background: var(--error, #f85149); }
|
|
203
|
+
|
|
204
|
+
.view-minimax-usage .minimax-quota-meta {
|
|
205
|
+
display: flex;
|
|
206
|
+
justify-content: space-between;
|
|
207
|
+
font-size: 11px;
|
|
208
|
+
color: var(--text-muted);
|
|
209
|
+
}
|
|
210
|
+
.view-minimax-usage .minimax-quota-meta strong {
|
|
211
|
+
color: var(--text);
|
|
212
|
+
font-weight: 600;
|
|
213
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/* ── Subscription Key card ──────────────────────────────────────── */
|
|
217
|
+
.view-minimax-usage .minimax-link {
|
|
218
|
+
color: var(--accent);
|
|
219
|
+
text-decoration: underline;
|
|
220
|
+
}
|
|
221
|
+
.view-minimax-usage .minimax-key-row {
|
|
222
|
+
display: flex;
|
|
223
|
+
align-items: center;
|
|
224
|
+
gap: 10px;
|
|
225
|
+
margin-top: 10px;
|
|
226
|
+
flex-wrap: wrap;
|
|
227
|
+
}
|
|
228
|
+
.view-minimax-usage .minimax-key-input-wrap {
|
|
229
|
+
position: relative;
|
|
230
|
+
flex: 1 1 320px;
|
|
231
|
+
display: flex;
|
|
232
|
+
align-items: center;
|
|
233
|
+
}
|
|
234
|
+
.view-minimax-usage .minimax-key-icon {
|
|
235
|
+
position: absolute;
|
|
236
|
+
left: 10px;
|
|
237
|
+
color: var(--text-muted);
|
|
238
|
+
pointer-events: none;
|
|
239
|
+
}
|
|
240
|
+
.view-minimax-usage .minimax-key-input {
|
|
241
|
+
width: 100%;
|
|
242
|
+
background: var(--bg-2);
|
|
243
|
+
border: 1px solid var(--border);
|
|
244
|
+
border-radius: 6px;
|
|
245
|
+
padding: 8px 36px 8px 32px;
|
|
246
|
+
color: var(--text);
|
|
247
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
248
|
+
font-size: 12px;
|
|
249
|
+
outline: none;
|
|
250
|
+
transition: border-color 120ms ease;
|
|
251
|
+
}
|
|
252
|
+
.view-minimax-usage .minimax-key-input:focus {
|
|
253
|
+
border-color: var(--accent);
|
|
254
|
+
}
|
|
255
|
+
.view-minimax-usage .minimax-key-input::placeholder {
|
|
256
|
+
color: var(--text-muted);
|
|
257
|
+
opacity: 0.7;
|
|
258
|
+
}
|
|
259
|
+
.view-minimax-usage .minimax-key-toggle {
|
|
260
|
+
position: absolute;
|
|
261
|
+
right: 6px;
|
|
262
|
+
width: 26px;
|
|
263
|
+
height: 26px;
|
|
264
|
+
display: inline-flex;
|
|
265
|
+
align-items: center;
|
|
266
|
+
justify-content: center;
|
|
267
|
+
background: transparent;
|
|
268
|
+
border: 0;
|
|
269
|
+
border-radius: 4px;
|
|
270
|
+
color: var(--text-muted);
|
|
271
|
+
cursor: pointer;
|
|
272
|
+
}
|
|
273
|
+
.view-minimax-usage .minimax-key-toggle:hover { color: var(--text); background: var(--bg-1); }
|
|
274
|
+
.view-minimax-usage .is-ok { color: var(--success, #3fb950); }
|
|
275
|
+
.view-minimax-usage .is-warn { color: var(--warning, #d29922); }
|
|
276
|
+
|
|
277
|
+
/* ── test prompt card ────────────────────────────────────────────── */
|
|
278
|
+
.view-minimax-usage .minimax-test-actions {
|
|
279
|
+
display: flex;
|
|
280
|
+
align-items: center;
|
|
281
|
+
gap: 12px;
|
|
282
|
+
flex-wrap: wrap;
|
|
283
|
+
margin-top: 8px;
|
|
284
|
+
}
|
|
285
|
+
.view-minimax-usage .minimax-test-prompt {
|
|
286
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
287
|
+
font-size: 12px;
|
|
288
|
+
color: var(--text-muted);
|
|
289
|
+
padding: 4px 8px;
|
|
290
|
+
background: var(--bg-2);
|
|
291
|
+
border-radius: 4px;
|
|
292
|
+
border: 1px solid var(--border);
|
|
293
|
+
}
|
|
294
|
+
.view-minimax-usage .minimax-test-result {
|
|
295
|
+
margin-top: 12px;
|
|
296
|
+
padding: 10px 12px;
|
|
297
|
+
border-radius: 6px;
|
|
298
|
+
display: flex;
|
|
299
|
+
gap: 10px;
|
|
300
|
+
align-items: flex-start;
|
|
301
|
+
font-size: 13px;
|
|
302
|
+
border: 1px solid transparent;
|
|
303
|
+
}
|
|
304
|
+
.view-minimax-usage .minimax-test-result.ok {
|
|
305
|
+
background: rgba(63, 185, 80, 0.08);
|
|
306
|
+
border-color: rgba(63, 185, 80, 0.30);
|
|
307
|
+
color: var(--text);
|
|
308
|
+
}
|
|
309
|
+
.view-minimax-usage .minimax-test-result.err {
|
|
310
|
+
background: rgba(248, 81, 73, 0.08);
|
|
311
|
+
border-color: rgba(248, 81, 73, 0.30);
|
|
312
|
+
color: var(--text);
|
|
313
|
+
}
|
|
314
|
+
.view-minimax-usage .minimax-test-body { flex: 1; min-width: 0; }
|
|
315
|
+
.view-minimax-usage .minimax-test-line { margin-bottom: 4px; }
|
|
316
|
+
.view-minimax-usage .minimax-test-line code {
|
|
317
|
+
font-size: 12px;
|
|
318
|
+
background: rgba(0,0,0,0.25);
|
|
319
|
+
padding: 0 4px;
|
|
320
|
+
border-radius: 3px;
|
|
321
|
+
}
|
|
322
|
+
.view-minimax-usage .minimax-test-content {
|
|
323
|
+
margin: 6px 0;
|
|
324
|
+
padding: 6px 8px;
|
|
325
|
+
background: var(--bg-2);
|
|
326
|
+
border-radius: 4px;
|
|
327
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
328
|
+
font-size: 12px;
|
|
329
|
+
}
|
|
330
|
+
.view-minimax-usage .minimax-test-usage {
|
|
331
|
+
font-size: 12px;
|
|
332
|
+
color: var(--text-muted);
|
|
333
|
+
}
|
|
334
|
+
.view-minimax-usage .minimax-test-usage code {
|
|
335
|
+
background: rgba(0,0,0,0.25);
|
|
336
|
+
padding: 0 4px;
|
|
337
|
+
border-radius: 3px;
|
|
338
|
+
font-size: 11px;
|
|
339
|
+
}
|
|
340
|
+
.view-minimax-usage .minimax-test-result pre {
|
|
341
|
+
margin: 0;
|
|
342
|
+
white-space: pre-wrap;
|
|
343
|
+
word-break: break-word;
|
|
344
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
345
|
+
font-size: 12px;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/* ── error card fallback ─────────────────────────────────────────── */
|
|
349
|
+
.view-minimax-usage .error-card {
|
|
350
|
+
display: flex;
|
|
351
|
+
align-items: flex-start;
|
|
352
|
+
gap: 12px;
|
|
353
|
+
padding: 14px 16px;
|
|
354
|
+
border-radius: 8px;
|
|
355
|
+
background: rgba(248, 81, 73, 0.06);
|
|
356
|
+
border: 1px solid rgba(248, 81, 73, 0.30);
|
|
357
|
+
color: var(--text);
|
|
358
|
+
}
|
|
359
|
+
.view-minimax-usage .error-card pre {
|
|
360
|
+
margin: 6px 0 0;
|
|
361
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
362
|
+
font-size: 12px;
|
|
363
|
+
white-space: pre-wrap;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* ── spinner helper (in case global .spin doesn't cover all cases) ─── */
|
|
367
|
+
.view-minimax-usage .spin { animation: minimax-spin 900ms linear infinite; }
|
|
368
|
+
@keyframes minimax-spin {
|
|
369
|
+
from { transform: rotate(0deg); }
|
|
370
|
+
to { transform: rotate(360deg); }
|
|
371
|
+
}
|