@wavespeed/cli 0.4.10 → 0.4.11
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/dist/commands/auth.js +2 -0
- package/dist/lib/api.js +26 -10
- package/package.json +2 -2
package/dist/commands/auth.js
CHANGED
|
@@ -6,6 +6,7 @@ import clipboard from 'clipboardy';
|
|
|
6
6
|
import { userConfig, getBaseUrl, getApiKey, loadProjectConfig, PROJECT_FILE } from '../lib/config.js';
|
|
7
7
|
import { LINKS } from '../lib/links.js';
|
|
8
8
|
import { clientAttributionHeaders } from '../lib/client-headers.js';
|
|
9
|
+
import { GET_TIMEOUT_MS } from '../lib/api.js';
|
|
9
10
|
const KEY_URL = 'https://wavespeed.ai/accesskey';
|
|
10
11
|
function mask(key) {
|
|
11
12
|
if (key.length < 12)
|
|
@@ -42,6 +43,7 @@ async function validateKey(apiKey, baseUrl) {
|
|
|
42
43
|
try {
|
|
43
44
|
res = await fetch(`${baseUrl}/api/v3/balance`, {
|
|
44
45
|
headers: { Authorization: `Bearer ${apiKey}`, ...clientAttributionHeaders() },
|
|
46
|
+
signal: AbortSignal.timeout(GET_TIMEOUT_MS),
|
|
45
47
|
});
|
|
46
48
|
}
|
|
47
49
|
catch (err) {
|
package/dist/lib/api.js
CHANGED
|
@@ -46,6 +46,7 @@ export async function fetchModels(opts = {}) {
|
|
|
46
46
|
throw new Error('No API key configured. Run `wavespeed login`.');
|
|
47
47
|
const res = await fetch(`${baseUrl}/api/v3/models`, {
|
|
48
48
|
headers: { Authorization: `Bearer ${apiKey}`, ...clientAttributionHeaders() },
|
|
49
|
+
signal: AbortSignal.timeout(GET_TIMEOUT_MS),
|
|
49
50
|
});
|
|
50
51
|
if (!res.ok) {
|
|
51
52
|
throw await httpError(res, 'GET', '/api/v3/models');
|
|
@@ -66,6 +67,12 @@ export function clearModelsCache() {
|
|
|
66
67
|
/* nothing to clear */
|
|
67
68
|
}
|
|
68
69
|
}
|
|
70
|
+
// Per-request timeouts (no overall cap). A hung socket would otherwise stall
|
|
71
|
+
// the CLI forever. Read-only GETs are far below 30s in practice (result p99.9
|
|
72
|
+
// < 1s); the async submit gets more headroom because a timeout there is an
|
|
73
|
+
// ambiguous outcome, not a clean failure.
|
|
74
|
+
export const GET_TIMEOUT_MS = 30_000;
|
|
75
|
+
export const SUBMIT_TIMEOUT_MS = 60_000;
|
|
69
76
|
// --- Account + prediction endpoints (not exposed by the wavespeed SDK) ---
|
|
70
77
|
function authHeaders() {
|
|
71
78
|
const apiKey = getApiKey();
|
|
@@ -94,10 +101,10 @@ async function httpError(res, method, path) {
|
|
|
94
101
|
err.status = res.status;
|
|
95
102
|
return err;
|
|
96
103
|
}
|
|
97
|
-
async function apiGet(path
|
|
104
|
+
async function apiGet(path) {
|
|
98
105
|
const res = await fetch(`${getBaseUrl()}${path}`, {
|
|
99
106
|
headers: authHeaders(),
|
|
100
|
-
signal:
|
|
107
|
+
signal: AbortSignal.timeout(GET_TIMEOUT_MS),
|
|
101
108
|
});
|
|
102
109
|
if (!res.ok)
|
|
103
110
|
throw await httpError(res, 'GET', path);
|
|
@@ -106,11 +113,12 @@ async function apiGet(path, opts = {}) {
|
|
|
106
113
|
throw new Error(json.message || `API returned code ${json.code}`);
|
|
107
114
|
return json.data;
|
|
108
115
|
}
|
|
109
|
-
async function apiPost(path, body) {
|
|
116
|
+
async function apiPost(path, body, opts = {}) {
|
|
110
117
|
const res = await fetch(`${getBaseUrl()}${path}`, {
|
|
111
118
|
method: 'POST',
|
|
112
119
|
headers: { ...authHeaders(), 'Content-Type': 'application/json' },
|
|
113
120
|
body: JSON.stringify(body),
|
|
121
|
+
signal: opts.timeoutMs ? AbortSignal.timeout(opts.timeoutMs) : undefined,
|
|
114
122
|
});
|
|
115
123
|
if (!res.ok)
|
|
116
124
|
throw await httpError(res, 'POST', path);
|
|
@@ -142,13 +150,8 @@ export async function fetchHistory(query = {}) {
|
|
|
142
150
|
body.status = query.status;
|
|
143
151
|
return apiPost('/api/v3/predictions', body);
|
|
144
152
|
}
|
|
145
|
-
// A hung socket would otherwise stall the CLI forever. 30s is far above a
|
|
146
|
-
// healthy status read, so it only trips on a dead connection.
|
|
147
|
-
const POLL_REQUEST_TIMEOUT_MS = 30_000;
|
|
148
153
|
export async function fetchPrediction(id) {
|
|
149
|
-
return apiGet(`/api/v3/predictions/${id}/result
|
|
150
|
-
timeoutMs: POLL_REQUEST_TIMEOUT_MS,
|
|
151
|
-
});
|
|
154
|
+
return apiGet(`/api/v3/predictions/${id}/result`);
|
|
152
155
|
}
|
|
153
156
|
// Same set as wavespeed-python. A thrown error with no HTTP status is a
|
|
154
157
|
// network failure or timeout; envelope/JSON errors carry no status either but
|
|
@@ -200,7 +203,20 @@ export async function submitPrediction(model, input, opts = {}) {
|
|
|
200
203
|
const body = { ...input };
|
|
201
204
|
if (opts.sync)
|
|
202
205
|
body.enable_sync_mode = true;
|
|
203
|
-
|
|
206
|
+
// sync mode legitimately holds the request until the task finishes, so only
|
|
207
|
+
// async submits get the per-request timeout.
|
|
208
|
+
try {
|
|
209
|
+
return await apiPost(`/api/v3/${model}`, body, {
|
|
210
|
+
timeoutMs: opts.sync ? undefined : SUBMIT_TIMEOUT_MS,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
// Never retried: the server may already have created (and billed) the task.
|
|
215
|
+
if (err?.name === 'TimeoutError') {
|
|
216
|
+
throw new Error(`Submission outcome unknown: no response within ${SUBMIT_TIMEOUT_MS / 1000}s. The task may have been created — run \`wavespeed history\` to check before retrying.`);
|
|
217
|
+
}
|
|
218
|
+
throw err;
|
|
219
|
+
}
|
|
204
220
|
}
|
|
205
221
|
/**
|
|
206
222
|
* Poll a prediction until it reaches a terminal status. `onTick` fires each
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wavespeed/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.11",
|
|
4
4
|
"description": "WaveSpeed CLI — one command to run any WaveSpeed AI model from your terminal.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"conf": "^13.0.0",
|
|
57
57
|
"open": "^10.1.0",
|
|
58
58
|
"ora": "^8.1.0",
|
|
59
|
-
"wavespeed": "^0.3.
|
|
59
|
+
"wavespeed": "^0.3.4"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/node": "^20.14.0",
|