scalemax 0.1.0 → 0.1.1
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 +2 -0
- package/dist/utils/api.js +23 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -116,6 +116,8 @@ List models:
|
|
|
116
116
|
npx scalemax models
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
The model list is fetched live from `https://api.scalemax.pro/v1/models` every time, so disabled or unsupported models disappear immediately without manual cache cleanup.
|
|
120
|
+
|
|
119
121
|
Run diagnostics:
|
|
120
122
|
|
|
121
123
|
```bash
|
package/dist/utils/api.js
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
import { SCALEMAX_BASE_URL } from '../constants.js';
|
|
2
|
+
async function friendlyError(res) {
|
|
3
|
+
let body = '';
|
|
4
|
+
try {
|
|
5
|
+
body = await res.text();
|
|
6
|
+
}
|
|
7
|
+
catch { }
|
|
8
|
+
let parsed;
|
|
9
|
+
try {
|
|
10
|
+
parsed = JSON.parse(body);
|
|
11
|
+
}
|
|
12
|
+
catch { }
|
|
13
|
+
const message = parsed?.error?.message || parsed?.message || '';
|
|
14
|
+
if (res.status === 400 || res.status === 404)
|
|
15
|
+
return message || 'The selected model is not currently supported. Please choose another available model.';
|
|
16
|
+
if (res.status === 401 || res.status === 403)
|
|
17
|
+
return message || 'Your API key was rejected. Run `scalemax login` and paste a valid key.';
|
|
18
|
+
if (res.status >= 500)
|
|
19
|
+
return message || 'ScaleMax is temporarily unavailable. Please try again shortly.';
|
|
20
|
+
return message || `HTTP ${res.status}`;
|
|
21
|
+
}
|
|
2
22
|
async function request(path, apiKey, init = {}) {
|
|
3
23
|
const headers = new Headers(init.headers);
|
|
4
24
|
if (apiKey)
|
|
5
25
|
headers.set('Authorization', `Bearer ${apiKey}`);
|
|
26
|
+
headers.set('Cache-Control', 'no-cache');
|
|
6
27
|
if (!headers.has('Content-Type') && init.body)
|
|
7
28
|
headers.set('Content-Type', 'application/json');
|
|
8
29
|
return fetch(`${SCALEMAX_BASE_URL}${path}`, { ...init, headers });
|
|
@@ -11,7 +32,7 @@ export async function validateApiKey(apiKey) {
|
|
|
11
32
|
try {
|
|
12
33
|
const res = await request('/models', apiKey);
|
|
13
34
|
if (!res.ok)
|
|
14
|
-
return { ok: false, models: [], error:
|
|
35
|
+
return { ok: false, models: [], error: await friendlyError(res) };
|
|
15
36
|
const data = await res.json();
|
|
16
37
|
return { ok: Array.isArray(data.data), models: data.data || [] };
|
|
17
38
|
}
|
|
@@ -24,7 +45,7 @@ export async function testStreaming(apiKey, model) {
|
|
|
24
45
|
try {
|
|
25
46
|
const res = await request('/chat/completions', apiKey, { method: 'POST', body: JSON.stringify({ model: selected, stream: true, max_tokens: 8, messages: [{ role: 'user', content: 'Say OK' }] }) });
|
|
26
47
|
if (!res.ok)
|
|
27
|
-
return { ok: false, error:
|
|
48
|
+
return { ok: false, error: await friendlyError(res) };
|
|
28
49
|
const ct = res.headers.get('content-type') || '';
|
|
29
50
|
if (!ct.includes('text/event-stream'))
|
|
30
51
|
return { ok: false, error: `Expected event stream, got ${ct}` };
|