@opengeni/xai-subscription 0.1.0
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/LICENSE +190 -0
- package/README.md +20 -0
- package/dist/bounded-operation.d.ts +8 -0
- package/dist/chunk-JEFGIUGN.js +80 -0
- package/dist/chunk-JEFGIUGN.js.map +1 -0
- package/dist/constants.d.ts +32 -0
- package/dist/constants.js +69 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors.d.ts +12 -0
- package/dist/fetch.d.ts +7 -0
- package/dist/images.d.ts +22 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +1245 -0
- package/dist/index.js.map +1 -0
- package/dist/models.d.ts +18 -0
- package/dist/normalize.d.ts +6 -0
- package/dist/oauth.d.ts +55 -0
- package/dist/proxy.d.ts +17 -0
- package/dist/quota.d.ts +24 -0
- package/dist/request-context.d.ts +26 -0
- package/dist/video.d.ts +53 -0
- package/package.json +45 -0
- package/src/bounded-operation.ts +33 -0
- package/src/constants.ts +53 -0
- package/src/errors.ts +34 -0
- package/src/fetch.ts +234 -0
- package/src/images.ts +176 -0
- package/src/index.ts +12 -0
- package/src/models.ts +99 -0
- package/src/normalize.ts +146 -0
- package/src/oauth.ts +335 -0
- package/src/proxy.ts +86 -0
- package/src/quota.ts +101 -0
- package/src/request-context.ts +31 -0
- package/src/video.ts +388 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1245 @@
|
|
|
1
|
+
import {
|
|
2
|
+
XAI_CLIENT_MODE,
|
|
3
|
+
XAI_CLIENT_VERSION,
|
|
4
|
+
XAI_DEVICE_AUTHORIZATION_URL,
|
|
5
|
+
XAI_DEVICE_CODE_GRANT_TYPE,
|
|
6
|
+
XAI_IMAGE_MODEL,
|
|
7
|
+
XAI_IMAGE_REQUEST_TIMEOUT_MS,
|
|
8
|
+
XAI_OAUTH_CLIENT_ID,
|
|
9
|
+
XAI_OAUTH_ISSUER,
|
|
10
|
+
XAI_OAUTH_OPERATION_TIMEOUT_MS,
|
|
11
|
+
XAI_OAUTH_SCOPES,
|
|
12
|
+
XAI_PUBLIC_API_BASE_URL,
|
|
13
|
+
XAI_REFRESH_FALLBACK_MS,
|
|
14
|
+
XAI_REFRESH_WINDOW_MS,
|
|
15
|
+
XAI_RESPONSE_SDK_OUTER_TIMEOUT_MS,
|
|
16
|
+
XAI_SUBSCRIPTION_AUTO_COMPACTION_PERCENT,
|
|
17
|
+
XAI_SUBSCRIPTION_EFFECTIVE_CONTEXT_PERCENT,
|
|
18
|
+
XAI_SUBSCRIPTION_MODEL_AUTO_COMPACT_TOKEN_LIMIT,
|
|
19
|
+
XAI_SUBSCRIPTION_MODEL_CONTEXT_WINDOW_TOKENS,
|
|
20
|
+
XAI_SUBSCRIPTION_MODEL_EFFECTIVE_CONTEXT_WINDOW_TOKENS,
|
|
21
|
+
XAI_SUBSCRIPTION_MODEL_ID_PREFIX,
|
|
22
|
+
XAI_SUBSCRIPTION_MODEL_SLUGS,
|
|
23
|
+
XAI_SUBSCRIPTION_PROVIDER_ID,
|
|
24
|
+
XAI_SUBSCRIPTION_PROXY_BASE_URL,
|
|
25
|
+
XAI_TOKEN_AUTH_HEADER_VALUE,
|
|
26
|
+
XAI_TOKEN_URL,
|
|
27
|
+
XAI_USERINFO_URL,
|
|
28
|
+
XAI_VIDEO_DOWNLOAD_TIMEOUT_MS,
|
|
29
|
+
XAI_VIDEO_GENERATION_TIMEOUT_MS,
|
|
30
|
+
XAI_VIDEO_MODEL,
|
|
31
|
+
XAI_VIDEO_POLL_INTERVAL_MS,
|
|
32
|
+
XAI_VIDEO_POLL_REQUEST_TIMEOUT_MS,
|
|
33
|
+
XAI_VIDEO_START_TIMEOUT_MS
|
|
34
|
+
} from "./chunk-JEFGIUGN.js";
|
|
35
|
+
|
|
36
|
+
// src/errors.ts
|
|
37
|
+
var XaiSubscriptionError = class extends Error {
|
|
38
|
+
constructor(kind, message, status) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.kind = kind;
|
|
41
|
+
this.status = status;
|
|
42
|
+
this.name = "XaiSubscriptionError";
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
var XaiSubscriptionReloginRequired = class extends XaiSubscriptionError {
|
|
46
|
+
constructor(message = "The SuperGrok connection is no longer valid. Reconnect the account.") {
|
|
47
|
+
super("relogin_required", message);
|
|
48
|
+
this.name = "XaiSubscriptionReloginRequired";
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var XaiSubscriptionTransientError = class extends XaiSubscriptionError {
|
|
52
|
+
constructor(message, status) {
|
|
53
|
+
super("transient", message, status);
|
|
54
|
+
this.name = "XaiSubscriptionTransientError";
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// src/bounded-operation.ts
|
|
59
|
+
async function runBoundedXaiOperation(operation, timeoutMs) {
|
|
60
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
61
|
+
throw new Error("xAI operation timeout must be positive");
|
|
62
|
+
}
|
|
63
|
+
const controller = new AbortController();
|
|
64
|
+
let timedOut = false;
|
|
65
|
+
let timeout;
|
|
66
|
+
const work = operation(controller.signal).then(
|
|
67
|
+
(value) => ({ ok: true, value }),
|
|
68
|
+
() => ({
|
|
69
|
+
ok: false,
|
|
70
|
+
reason: timedOut || controller.signal.aborted ? "timeout" : "network_error"
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
const deadline = new Promise((resolve) => {
|
|
74
|
+
timeout = setTimeout(() => {
|
|
75
|
+
timedOut = true;
|
|
76
|
+
controller.abort();
|
|
77
|
+
resolve({ ok: false, reason: "timeout" });
|
|
78
|
+
}, timeoutMs);
|
|
79
|
+
});
|
|
80
|
+
try {
|
|
81
|
+
return await Promise.race([work, deadline]);
|
|
82
|
+
} finally {
|
|
83
|
+
if (timeout) clearTimeout(timeout);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/oauth.ts
|
|
88
|
+
import {
|
|
89
|
+
OAUTH_MAX_RESPONSE_BYTES,
|
|
90
|
+
readResponseJsonBounded,
|
|
91
|
+
validateHttpUrl
|
|
92
|
+
} from "@opengeni/network";
|
|
93
|
+
function oauthHeaders() {
|
|
94
|
+
return new Headers({
|
|
95
|
+
accept: "application/json",
|
|
96
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
97
|
+
"user-agent": `opengeni/${XAI_CLIENT_VERSION}`,
|
|
98
|
+
"x-grok-client-version": XAI_CLIENT_VERSION,
|
|
99
|
+
"x-grok-client-surface": "headless"
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function positiveSeconds(value, fallback) {
|
|
103
|
+
const number = Number(value);
|
|
104
|
+
return Number.isFinite(number) && number > 0 ? Math.ceil(number) : fallback;
|
|
105
|
+
}
|
|
106
|
+
function requireNonEmptyString(value, field) {
|
|
107
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
108
|
+
throw new XaiSubscriptionError("invalid_response", `xAI OAuth response is missing ${field}`);
|
|
109
|
+
}
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
function nullableString(value) {
|
|
113
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
114
|
+
}
|
|
115
|
+
function validateUserCode(userCode) {
|
|
116
|
+
if (![...userCode].every((char) => /[A-Za-z0-9-]/.test(char))) {
|
|
117
|
+
throw new XaiSubscriptionError("invalid_response", "xAI returned an invalid user code");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function validateVerificationUri(uri) {
|
|
121
|
+
try {
|
|
122
|
+
return validateHttpUrl(uri, {
|
|
123
|
+
allowLoopbackHttp: true,
|
|
124
|
+
label: "xAI device verification"
|
|
125
|
+
});
|
|
126
|
+
} catch {
|
|
127
|
+
throw new XaiSubscriptionError("invalid_response", "xAI returned an invalid verification URL");
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async function boundedFetchJson(label, input, init, options) {
|
|
131
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
132
|
+
const timeoutMs = options.timeoutMs ?? XAI_OAUTH_OPERATION_TIMEOUT_MS;
|
|
133
|
+
const fetched = await runBoundedXaiOperation(async (signal) => {
|
|
134
|
+
const response = await fetchImpl(input, { ...init, signal });
|
|
135
|
+
const body = await readResponseJsonBounded(
|
|
136
|
+
response,
|
|
137
|
+
OAUTH_MAX_RESPONSE_BYTES,
|
|
138
|
+
label,
|
|
139
|
+
{ signal }
|
|
140
|
+
);
|
|
141
|
+
return { response, body };
|
|
142
|
+
}, timeoutMs);
|
|
143
|
+
if (!fetched.ok) {
|
|
144
|
+
throw new XaiSubscriptionTransientError(`xAI ${label} ${fetched.reason}`);
|
|
145
|
+
}
|
|
146
|
+
return fetched.value;
|
|
147
|
+
}
|
|
148
|
+
async function requestXaiDeviceCode(options = {}) {
|
|
149
|
+
const { response, body } = await boundedFetchJson(
|
|
150
|
+
"device code request",
|
|
151
|
+
options.deviceAuthorizationUrl ?? XAI_DEVICE_AUTHORIZATION_URL,
|
|
152
|
+
{
|
|
153
|
+
method: "POST",
|
|
154
|
+
headers: oauthHeaders(),
|
|
155
|
+
body: new URLSearchParams({
|
|
156
|
+
client_id: options.clientId ?? XAI_OAUTH_CLIENT_ID,
|
|
157
|
+
scope: XAI_OAUTH_SCOPES.join(" "),
|
|
158
|
+
referrer: "opengeni"
|
|
159
|
+
}).toString()
|
|
160
|
+
},
|
|
161
|
+
options
|
|
162
|
+
);
|
|
163
|
+
if (response.status === 404) {
|
|
164
|
+
throw new XaiSubscriptionError(
|
|
165
|
+
"not_enabled",
|
|
166
|
+
"SuperGrok device-code login is not enabled by xAI",
|
|
167
|
+
404
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
if (!response.ok) {
|
|
171
|
+
throw new XaiSubscriptionTransientError(
|
|
172
|
+
`xAI device code request failed (${response.status})`,
|
|
173
|
+
response.status
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
const deviceCode = requireNonEmptyString(body.device_code, "device_code");
|
|
177
|
+
const userCode = requireNonEmptyString(body.user_code, "user_code");
|
|
178
|
+
const verificationUri = validateVerificationUri(
|
|
179
|
+
requireNonEmptyString(body.verification_uri, "verification_uri")
|
|
180
|
+
);
|
|
181
|
+
const verificationUriComplete = nullableString(body.verification_uri_complete);
|
|
182
|
+
validateUserCode(userCode);
|
|
183
|
+
return {
|
|
184
|
+
deviceCode,
|
|
185
|
+
userCode,
|
|
186
|
+
verificationUri,
|
|
187
|
+
verificationUriComplete: verificationUriComplete ? validateVerificationUri(verificationUriComplete) : null,
|
|
188
|
+
expiresInSeconds: positiveSeconds(body.expires_in, 5 * 60),
|
|
189
|
+
intervalSeconds: Math.max(1, positiveSeconds(body.interval, 5))
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
async function pollXaiDeviceCode(input, options = {}) {
|
|
193
|
+
const { response, body } = await boundedFetchJson(
|
|
194
|
+
"device token exchange",
|
|
195
|
+
options.tokenUrl ?? XAI_TOKEN_URL,
|
|
196
|
+
{
|
|
197
|
+
method: "POST",
|
|
198
|
+
headers: oauthHeaders(),
|
|
199
|
+
body: new URLSearchParams({
|
|
200
|
+
grant_type: XAI_DEVICE_CODE_GRANT_TYPE,
|
|
201
|
+
client_id: options.clientId ?? XAI_OAUTH_CLIENT_ID,
|
|
202
|
+
device_code: input.deviceCode
|
|
203
|
+
}).toString()
|
|
204
|
+
},
|
|
205
|
+
options
|
|
206
|
+
);
|
|
207
|
+
if (response.ok) {
|
|
208
|
+
return { status: "authorized", tokens: parseTokenResponse(body, true) };
|
|
209
|
+
}
|
|
210
|
+
const code = nullableString(body.error);
|
|
211
|
+
if (code === "authorization_pending") {
|
|
212
|
+
return { status: "pending", intervalSeconds: Math.max(1, input.intervalSeconds) };
|
|
213
|
+
}
|
|
214
|
+
if (code === "slow_down") {
|
|
215
|
+
return { status: "slow_down", intervalSeconds: Math.max(1, input.intervalSeconds) + 5 };
|
|
216
|
+
}
|
|
217
|
+
if (code === "access_denied" || code === "authorization_denied") {
|
|
218
|
+
return { status: "denied" };
|
|
219
|
+
}
|
|
220
|
+
if (code === "expired_token") {
|
|
221
|
+
return { status: "expired" };
|
|
222
|
+
}
|
|
223
|
+
throw new XaiSubscriptionTransientError(
|
|
224
|
+
`xAI device token exchange failed (${response.status})`,
|
|
225
|
+
response.status
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
async function refreshXaiToken(refreshToken, options = {}) {
|
|
229
|
+
const { response, body } = await boundedFetchJson(
|
|
230
|
+
"token refresh",
|
|
231
|
+
options.tokenUrl ?? XAI_TOKEN_URL,
|
|
232
|
+
{
|
|
233
|
+
method: "POST",
|
|
234
|
+
headers: oauthHeaders(),
|
|
235
|
+
body: new URLSearchParams({
|
|
236
|
+
grant_type: "refresh_token",
|
|
237
|
+
refresh_token: refreshToken,
|
|
238
|
+
client_id: options.clientId ?? XAI_OAUTH_CLIENT_ID
|
|
239
|
+
}).toString()
|
|
240
|
+
},
|
|
241
|
+
options
|
|
242
|
+
);
|
|
243
|
+
if (!response.ok) {
|
|
244
|
+
const code = nullableString(body.error);
|
|
245
|
+
if (response.status === 401 || code === "invalid_grant" || code === "invalid_token" || code === "access_denied") {
|
|
246
|
+
throw new XaiSubscriptionReloginRequired();
|
|
247
|
+
}
|
|
248
|
+
throw new XaiSubscriptionTransientError(
|
|
249
|
+
`xAI token refresh failed (${response.status})`,
|
|
250
|
+
response.status
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
const parsed = parseTokenResponse(body, false);
|
|
254
|
+
return {
|
|
255
|
+
...parsed,
|
|
256
|
+
refreshToken: parsed.refreshToken || refreshToken
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function parseTokenResponse(body, requireRefresh) {
|
|
260
|
+
const accessToken = requireNonEmptyString(body.access_token, "access_token");
|
|
261
|
+
const refreshToken = nullableString(body.refresh_token);
|
|
262
|
+
if (requireRefresh && !refreshToken) {
|
|
263
|
+
throw new XaiSubscriptionError(
|
|
264
|
+
"invalid_response",
|
|
265
|
+
"xAI OAuth response is missing refresh_token"
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
accessToken,
|
|
270
|
+
refreshToken: refreshToken ?? "",
|
|
271
|
+
idToken: nullableString(body.id_token),
|
|
272
|
+
tokenType: nullableString(body.token_type),
|
|
273
|
+
scope: nullableString(body.scope),
|
|
274
|
+
expiresInSeconds: positiveSeconds(body.expires_in, 60 * 60)
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
async function fetchXaiVerifiedIdentity(accessToken, options = {}) {
|
|
278
|
+
const headers = new Headers({
|
|
279
|
+
accept: "application/json",
|
|
280
|
+
authorization: `Bearer ${accessToken}`,
|
|
281
|
+
"user-agent": `opengeni/${XAI_CLIENT_VERSION}`,
|
|
282
|
+
"x-grok-client-version": XAI_CLIENT_VERSION
|
|
283
|
+
});
|
|
284
|
+
const { response, body } = await boundedFetchJson(
|
|
285
|
+
"userinfo request",
|
|
286
|
+
options.userinfoUrl ?? XAI_USERINFO_URL,
|
|
287
|
+
{ method: "GET", headers },
|
|
288
|
+
options
|
|
289
|
+
);
|
|
290
|
+
if (response.status === 401 || response.status === 403) {
|
|
291
|
+
throw new XaiSubscriptionReloginRequired();
|
|
292
|
+
}
|
|
293
|
+
if (!response.ok) {
|
|
294
|
+
throw new XaiSubscriptionTransientError(
|
|
295
|
+
`xAI userinfo request failed (${response.status})`,
|
|
296
|
+
response.status
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
subject: requireNonEmptyString(body.sub, "userinfo sub"),
|
|
301
|
+
email: nullableString(body.email),
|
|
302
|
+
emailVerified: typeof body.email_verified === "boolean" ? body.email_verified : null,
|
|
303
|
+
name: nullableString(body.name)
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function decodeXaiJwtPayload(jwt) {
|
|
307
|
+
const payload = jwt.split(".")[1];
|
|
308
|
+
if (!payload) return null;
|
|
309
|
+
try {
|
|
310
|
+
return JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
|
|
311
|
+
} catch {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function xaiAccessTokenExpiry(accessToken) {
|
|
316
|
+
const payload = decodeXaiJwtPayload(accessToken);
|
|
317
|
+
return typeof payload?.exp === "number" ? new Date(payload.exp * 1e3) : null;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// src/request-context.ts
|
|
321
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
322
|
+
var xaiSubscriptionRequestStorage = new AsyncLocalStorage();
|
|
323
|
+
|
|
324
|
+
// src/normalize.ts
|
|
325
|
+
var XAI_INTERNAL_MODEL_HANDOFF_PREFIX = "supergrok/";
|
|
326
|
+
function normalizeXaiSubscriptionRequestBody(value, resolveModel, hostedSearch) {
|
|
327
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
328
|
+
throw new Error("SuperGrok subscription request body must be a JSON object");
|
|
329
|
+
}
|
|
330
|
+
const body = { ...value };
|
|
331
|
+
if (typeof body.model !== "string") {
|
|
332
|
+
throw new Error("SuperGrok subscription request is missing model");
|
|
333
|
+
}
|
|
334
|
+
const candidate = body.model.startsWith(XAI_INTERNAL_MODEL_HANDOFF_PREFIX) ? body.model.slice(XAI_INTERNAL_MODEL_HANDOFF_PREFIX.length) : body.model;
|
|
335
|
+
body.model = resolveModel(candidate);
|
|
336
|
+
body.store = false;
|
|
337
|
+
const include = Array.isArray(body.include) ? body.include.filter((entry) => typeof entry === "string") : [];
|
|
338
|
+
if (!include.includes("reasoning.encrypted_content")) {
|
|
339
|
+
include.push("reasoning.encrypted_content");
|
|
340
|
+
}
|
|
341
|
+
body.include = include;
|
|
342
|
+
const tools = Array.isArray(body.tools) ? body.tools.map(normalizeXaiSubscriptionTool) : [];
|
|
343
|
+
appendHostedTool(tools, "web_search", hostedSearch?.webSearch);
|
|
344
|
+
appendHostedTool(tools, "x_search", hostedSearch?.xSearch);
|
|
345
|
+
if (tools.length > 0) body.tools = tools;
|
|
346
|
+
return body;
|
|
347
|
+
}
|
|
348
|
+
function normalizeXaiSubscriptionTool(tool) {
|
|
349
|
+
if (!tool || typeof tool !== "object" || Array.isArray(tool)) return tool;
|
|
350
|
+
const record2 = tool;
|
|
351
|
+
if (record2.type !== "web_search") return tool;
|
|
352
|
+
const { search_context_size: _unsupported, ...supported } = record2;
|
|
353
|
+
return supported;
|
|
354
|
+
}
|
|
355
|
+
function appendHostedTool(tools, type, options) {
|
|
356
|
+
if (!options) return;
|
|
357
|
+
if (tools.some(
|
|
358
|
+
(tool) => tool && typeof tool === "object" && !Array.isArray(tool) && tool.type === type
|
|
359
|
+
)) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
tools.push(normalizeXaiSubscriptionTool(options === true ? { type } : { type, ...options }));
|
|
363
|
+
}
|
|
364
|
+
function normalizeXaiResponseEventJson(value) {
|
|
365
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
366
|
+
return { value, finalContextTokens: null };
|
|
367
|
+
}
|
|
368
|
+
const event = value;
|
|
369
|
+
const response = event.response && typeof event.response === "object" && !Array.isArray(event.response) ? { ...event.response } : null;
|
|
370
|
+
if (!response) return { value, finalContextTokens: null };
|
|
371
|
+
let changed = false;
|
|
372
|
+
if (Array.isArray(response.tools)) {
|
|
373
|
+
const filtered = response.tools.filter((tool) => isOpenAiSdkResponseTool(tool));
|
|
374
|
+
if (filtered.length !== response.tools.length) {
|
|
375
|
+
response.tools = filtered;
|
|
376
|
+
changed = true;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
let finalContextTokens = null;
|
|
380
|
+
if (event.type === "response.completed" || event.type === "response.incomplete") {
|
|
381
|
+
const usage = response.usage && typeof response.usage === "object" && !Array.isArray(response.usage) ? { ...response.usage } : null;
|
|
382
|
+
const context = usage?.context_details && typeof usage.context_details === "object" && !Array.isArray(usage.context_details) ? usage.context_details : null;
|
|
383
|
+
const inputTokens = finiteNonNegativeInteger(context?.input_tokens);
|
|
384
|
+
const outputTokens = finiteNonNegativeInteger(context?.output_tokens);
|
|
385
|
+
if (usage && inputTokens !== null && outputTokens !== null) {
|
|
386
|
+
finalContextTokens = inputTokens + outputTokens;
|
|
387
|
+
usage.total_tokens = finalContextTokens;
|
|
388
|
+
response.usage = usage;
|
|
389
|
+
changed = true;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return {
|
|
393
|
+
value: changed ? { ...event, response } : value,
|
|
394
|
+
finalContextTokens
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function finiteNonNegativeInteger(value) {
|
|
398
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
|
|
399
|
+
}
|
|
400
|
+
function isOpenAiSdkResponseTool(tool) {
|
|
401
|
+
if (!tool || typeof tool !== "object" || Array.isArray(tool)) return false;
|
|
402
|
+
const type = tool.type;
|
|
403
|
+
return typeof type === "string" && [
|
|
404
|
+
"function",
|
|
405
|
+
"file_search",
|
|
406
|
+
"computer_use_preview",
|
|
407
|
+
"computer",
|
|
408
|
+
"web_search",
|
|
409
|
+
"web_search_preview",
|
|
410
|
+
"code_interpreter",
|
|
411
|
+
"image_generation",
|
|
412
|
+
"local_shell",
|
|
413
|
+
"shell",
|
|
414
|
+
"apply_patch",
|
|
415
|
+
"mcp",
|
|
416
|
+
"custom"
|
|
417
|
+
].includes(type);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// src/fetch.ts
|
|
421
|
+
import { randomUUID } from "crypto";
|
|
422
|
+
var REPLAYABLE_REQUEST_BODY_FACTORY = Symbol.for("opengeni.replayable-request-body-factory");
|
|
423
|
+
var XAI_SUBSCRIPTION_TRANSPORT_ERROR_HEADER = "x-opengeni-xai-subscription-transport-error";
|
|
424
|
+
var XAI_SUBSCRIPTION_REQUEST_BODY_NORMALIZED_HEADER = "x-opengeni-xai-subscription-body-normalized";
|
|
425
|
+
var XAI_SUBSCRIPTION_REQUEST_MODEL_HEADER = "x-opengeni-xai-subscription-model";
|
|
426
|
+
var XAI_SUBSCRIPTION_REQUEST_ID_HEADER = "x-opengeni-xai-subscription-request-id";
|
|
427
|
+
var MAX_ERROR_BODY_BYTES = 64 * 1024;
|
|
428
|
+
function xaiSubscriptionFetch(base) {
|
|
429
|
+
return async (input, init) => {
|
|
430
|
+
const context = xaiSubscriptionRequestStorage.getStore();
|
|
431
|
+
if (!context) throw new Error("SuperGrok subscription request context is unavailable");
|
|
432
|
+
const originalUrl = input instanceof Request ? input.url : String(input);
|
|
433
|
+
const url = new URL(originalUrl);
|
|
434
|
+
if (!url.pathname.endsWith("/responses")) {
|
|
435
|
+
throw new Error("SuperGrok subscription models require the Responses API");
|
|
436
|
+
}
|
|
437
|
+
const originalHeaders = new Headers(input instanceof Request ? input.headers : void 0);
|
|
438
|
+
if (init?.headers) {
|
|
439
|
+
new Headers(init.headers).forEach((value, key) => originalHeaders.set(key, value));
|
|
440
|
+
}
|
|
441
|
+
const normalized = originalHeaders.get(XAI_SUBSCRIPTION_REQUEST_BODY_NORMALIZED_HEADER) === "1";
|
|
442
|
+
const requestId = originalHeaders.get(XAI_SUBSCRIPTION_REQUEST_ID_HEADER) ?? randomUUID();
|
|
443
|
+
const handedOffModel = originalHeaders.get(XAI_SUBSCRIPTION_REQUEST_MODEL_HEADER);
|
|
444
|
+
originalHeaders.delete(XAI_SUBSCRIPTION_REQUEST_BODY_NORMALIZED_HEADER);
|
|
445
|
+
originalHeaders.delete(XAI_SUBSCRIPTION_REQUEST_ID_HEADER);
|
|
446
|
+
originalHeaders.delete(XAI_SUBSCRIPTION_REQUEST_MODEL_HEADER);
|
|
447
|
+
const replayableBodyFactory = init?.[REPLAYABLE_REQUEST_BODY_FACTORY];
|
|
448
|
+
const body = await requestBodyText(input, init, replayableBodyFactory);
|
|
449
|
+
const parsed = body ? JSON.parse(body) : {};
|
|
450
|
+
const normalizedBody = normalized ? parsed : normalizeXaiSubscriptionRequestBody(parsed, context.resolveModel, context.hostedSearch);
|
|
451
|
+
const model = handedOffModel ?? (typeof normalizedBody.model === "string" ? normalizedBody.model : "grok-4.6");
|
|
452
|
+
const send = async (refresh) => {
|
|
453
|
+
const token = refresh ? await context.refresh() : await context.getToken();
|
|
454
|
+
const headers = new Headers(originalHeaders);
|
|
455
|
+
headers.set("authorization", `Bearer ${token.accessToken}`);
|
|
456
|
+
headers.set("content-type", "application/json");
|
|
457
|
+
headers.set("accept", "text/event-stream");
|
|
458
|
+
headers.set("user-agent", `opengeni/${context.clientVersion || XAI_CLIENT_VERSION}`);
|
|
459
|
+
headers.set("x-grok-client-version", context.clientVersion || XAI_CLIENT_VERSION);
|
|
460
|
+
headers.set("x-grok-client-identifier", "opengeni");
|
|
461
|
+
headers.set("x-grok-client-mode", XAI_CLIENT_MODE);
|
|
462
|
+
headers.set("x-authenticateresponse", "authenticate-response");
|
|
463
|
+
headers.set("x-xai-token-auth", XAI_TOKEN_AUTH_HEADER_VALUE);
|
|
464
|
+
headers.set("x-userid", token.userId);
|
|
465
|
+
headers.set("x-grok-user-id", token.userId);
|
|
466
|
+
headers.set("x-grok-conv-id", context.sessionId);
|
|
467
|
+
headers.set("x-grok-session-id", context.sessionId);
|
|
468
|
+
headers.set("x-grok-req-id", requestId);
|
|
469
|
+
headers.set("x-grok-agent-id", context.turnId);
|
|
470
|
+
headers.set("x-grok-model-override", model);
|
|
471
|
+
return await base(url, {
|
|
472
|
+
...init,
|
|
473
|
+
method: init?.method ?? (input instanceof Request ? input.method : "POST"),
|
|
474
|
+
headers,
|
|
475
|
+
body: JSON.stringify(normalizedBody)
|
|
476
|
+
});
|
|
477
|
+
};
|
|
478
|
+
let response = await send(false);
|
|
479
|
+
if (response.status === 401) {
|
|
480
|
+
await response.body?.cancel().catch(() => void 0);
|
|
481
|
+
response = await send(true);
|
|
482
|
+
}
|
|
483
|
+
return await normalizeResponse(response, context.onFinalContextUsage);
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
async function requestBodyText(input, init, replayableBodyFactory) {
|
|
487
|
+
if (typeof init?.body === "string") return init.body;
|
|
488
|
+
if (input instanceof Request) return await input.clone().text();
|
|
489
|
+
if (replayableBodyFactory) return await new Response(replayableBodyFactory()).text();
|
|
490
|
+
if (init?.body === void 0 || init.body === null) return "";
|
|
491
|
+
throw new Error("SuperGrok subscription request body must be replayable JSON text");
|
|
492
|
+
}
|
|
493
|
+
async function normalizeResponse(response, onFinalContextUsage) {
|
|
494
|
+
if (!response.ok) {
|
|
495
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
496
|
+
const bounded = bytes.byteLength > MAX_ERROR_BODY_BYTES ? bytes.slice(0, MAX_ERROR_BODY_BYTES) : bytes;
|
|
497
|
+
const headers = new Headers(response.headers);
|
|
498
|
+
headers.set(XAI_SUBSCRIPTION_TRANSPORT_ERROR_HEADER, "1");
|
|
499
|
+
return new Response(bounded, {
|
|
500
|
+
status: response.status,
|
|
501
|
+
statusText: response.statusText,
|
|
502
|
+
headers
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
if (!response.body) return response;
|
|
506
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
507
|
+
if (!contentType.includes("text/event-stream")) {
|
|
508
|
+
const value = await response.json();
|
|
509
|
+
const normalized = normalizeXaiResponseEventJson({
|
|
510
|
+
type: "response.completed",
|
|
511
|
+
response: value
|
|
512
|
+
});
|
|
513
|
+
emitContextUsage(normalized.value, normalized.finalContextTokens, onFinalContextUsage);
|
|
514
|
+
const responseValue = normalized.value && typeof normalized.value === "object" && !Array.isArray(normalized.value) ? normalized.value.response : value;
|
|
515
|
+
return Response.json(responseValue, {
|
|
516
|
+
status: response.status,
|
|
517
|
+
statusText: response.statusText,
|
|
518
|
+
headers: response.headers
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
const reader = response.body.getReader();
|
|
522
|
+
const decoder = new TextDecoder();
|
|
523
|
+
const encoder = new TextEncoder();
|
|
524
|
+
let pending = "";
|
|
525
|
+
const body = new ReadableStream({
|
|
526
|
+
async pull(controller) {
|
|
527
|
+
const chunk = await reader.read();
|
|
528
|
+
pending += decoder.decode(chunk.value, { stream: !chunk.done });
|
|
529
|
+
const parts = pending.split("\n\n");
|
|
530
|
+
pending = parts.pop() ?? "";
|
|
531
|
+
for (const part of parts)
|
|
532
|
+
controller.enqueue(encoder.encode(`${normalizeSseEvent(part, onFinalContextUsage)}
|
|
533
|
+
|
|
534
|
+
`));
|
|
535
|
+
if (chunk.done) {
|
|
536
|
+
if (pending)
|
|
537
|
+
controller.enqueue(encoder.encode(normalizeSseEvent(pending, onFinalContextUsage)));
|
|
538
|
+
controller.close();
|
|
539
|
+
}
|
|
540
|
+
},
|
|
541
|
+
cancel(reason) {
|
|
542
|
+
return reader.cancel(reason);
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
return new Response(body, {
|
|
546
|
+
status: response.status,
|
|
547
|
+
statusText: response.statusText,
|
|
548
|
+
headers: response.headers
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
function normalizeSseEvent(block, onFinalContextUsage) {
|
|
552
|
+
const lines = block.split("\n");
|
|
553
|
+
return lines.map((line) => {
|
|
554
|
+
if (!line.startsWith("data:")) return line;
|
|
555
|
+
const data = line.slice(5).trimStart();
|
|
556
|
+
if (!data || data === "[DONE]") return line;
|
|
557
|
+
try {
|
|
558
|
+
const normalized = normalizeXaiResponseEventJson(JSON.parse(data));
|
|
559
|
+
emitContextUsage(normalized.value, normalized.finalContextTokens, onFinalContextUsage);
|
|
560
|
+
return `data: ${JSON.stringify(normalized.value)}`;
|
|
561
|
+
} catch {
|
|
562
|
+
return line;
|
|
563
|
+
}
|
|
564
|
+
}).join("\n");
|
|
565
|
+
}
|
|
566
|
+
function emitContextUsage(value, finalContextTokens, sink) {
|
|
567
|
+
if (finalContextTokens === null || !sink) return;
|
|
568
|
+
const response = value && typeof value === "object" && !Array.isArray(value) ? value.response : null;
|
|
569
|
+
const usage = response && typeof response === "object" && !Array.isArray(response) ? response.usage : null;
|
|
570
|
+
const context = usage && typeof usage === "object" && !Array.isArray(usage) ? usage.context_details : null;
|
|
571
|
+
if (!context || typeof context !== "object" || Array.isArray(context)) return;
|
|
572
|
+
const inputTokens = Number(context.input_tokens);
|
|
573
|
+
const outputTokens = Number(context.output_tokens);
|
|
574
|
+
if (!Number.isSafeInteger(inputTokens) || !Number.isSafeInteger(outputTokens)) return;
|
|
575
|
+
try {
|
|
576
|
+
sink({ inputTokens, outputTokens, totalTokens: finalContextTokens });
|
|
577
|
+
} catch {
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
function isXaiSubscriptionTransportError(error) {
|
|
581
|
+
let current = error;
|
|
582
|
+
for (let depth = 0; depth < 6 && current && typeof current === "object"; depth += 1) {
|
|
583
|
+
const value = current;
|
|
584
|
+
const headers = value.headers;
|
|
585
|
+
if (headers && typeof headers === "object" && typeof headers.get === "function" && headers.get(XAI_SUBSCRIPTION_TRANSPORT_ERROR_HEADER) === "1") {
|
|
586
|
+
return true;
|
|
587
|
+
}
|
|
588
|
+
current = value.cause;
|
|
589
|
+
}
|
|
590
|
+
return false;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// src/proxy.ts
|
|
594
|
+
import { OAUTH_MAX_RESPONSE_BYTES as OAUTH_MAX_RESPONSE_BYTES2, pinnedFetch, readResponseJsonBounded as readResponseJsonBounded2 } from "@opengeni/network";
|
|
595
|
+
var defaultProxyFetch = async (input, init) => await pinnedFetch(
|
|
596
|
+
input,
|
|
597
|
+
init,
|
|
598
|
+
{ environment: "production", integrationsAllowPrivateNetworkTargets: false },
|
|
599
|
+
{ label: "xAI subscription proxy", requireHttpsOutsideLocalTest: true }
|
|
600
|
+
);
|
|
601
|
+
async function fetchXaiProxyJson(input) {
|
|
602
|
+
const fetchImpl = input.fetch ?? defaultProxyFetch;
|
|
603
|
+
const timeoutMs = input.timeoutMs ?? 15e3;
|
|
604
|
+
const maxBytes = input.maxBytes ?? OAUTH_MAX_RESPONSE_BYTES2;
|
|
605
|
+
const url = `${(input.baseUrl ?? XAI_SUBSCRIPTION_PROXY_BASE_URL).replace(/\/+$/, "")}/${input.path.replace(/^\/+/, "")}`;
|
|
606
|
+
const request = async (token, signal) => {
|
|
607
|
+
const headers = xaiSubscriptionProxyHeaders(token, input.context.clientVersion);
|
|
608
|
+
return await fetchImpl(url, { method: "GET", redirect: "error", headers, signal });
|
|
609
|
+
};
|
|
610
|
+
const fetched = await runBoundedXaiOperation(async (signal) => {
|
|
611
|
+
let response = await request(await input.context.getToken(), signal);
|
|
612
|
+
if (response.status === 401) {
|
|
613
|
+
await response.body?.cancel().catch(() => void 0);
|
|
614
|
+
response = await request(await input.context.refresh(), signal);
|
|
615
|
+
}
|
|
616
|
+
if (response.status === 401 || response.status === 403) {
|
|
617
|
+
await response.body?.cancel().catch(() => void 0);
|
|
618
|
+
throw new XaiSubscriptionReloginRequired();
|
|
619
|
+
}
|
|
620
|
+
if (!response.ok) {
|
|
621
|
+
await response.body?.cancel().catch(() => void 0);
|
|
622
|
+
throw new XaiSubscriptionTransientError(
|
|
623
|
+
`xAI ${input.label} failed (${response.status})`,
|
|
624
|
+
response.status
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
return await readResponseJsonBounded2(response, maxBytes, `xAI ${input.label}`, { signal });
|
|
628
|
+
}, timeoutMs);
|
|
629
|
+
if (!fetched.ok) {
|
|
630
|
+
throw new XaiSubscriptionTransientError(`xAI ${input.label} ${fetched.reason}`);
|
|
631
|
+
}
|
|
632
|
+
return fetched.value;
|
|
633
|
+
}
|
|
634
|
+
function xaiSubscriptionProxyHeaders(token, clientVersion = XAI_CLIENT_VERSION) {
|
|
635
|
+
return new Headers({
|
|
636
|
+
accept: "application/json",
|
|
637
|
+
authorization: `Bearer ${token.accessToken}`,
|
|
638
|
+
"user-agent": `opengeni/${clientVersion}`,
|
|
639
|
+
"x-grok-client-version": clientVersion,
|
|
640
|
+
"x-grok-client-identifier": "opengeni",
|
|
641
|
+
"x-grok-client-mode": XAI_CLIENT_MODE,
|
|
642
|
+
"x-authenticateresponse": "authenticate-response",
|
|
643
|
+
"x-xai-token-auth": XAI_TOKEN_AUTH_HEADER_VALUE,
|
|
644
|
+
"x-userid": token.userId,
|
|
645
|
+
"x-grok-user-id": token.userId
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// src/quota.ts
|
|
650
|
+
async function fetchXaiSubscriptionQuota(input) {
|
|
651
|
+
const body = await fetchXaiProxyJson({
|
|
652
|
+
path: "billing?format=credits",
|
|
653
|
+
context: input.context,
|
|
654
|
+
...input.fetch ? { fetch: input.fetch } : {},
|
|
655
|
+
...input.timeoutMs ? { timeoutMs: input.timeoutMs } : {},
|
|
656
|
+
...input.baseUrl ? { baseUrl: input.baseUrl } : {},
|
|
657
|
+
label: "billing request"
|
|
658
|
+
});
|
|
659
|
+
const config = record(body.config);
|
|
660
|
+
const currentPeriod = record(config?.currentPeriod ?? config?.current_period);
|
|
661
|
+
const monthlyLimit = cents(config?.monthlyLimit ?? config?.monthly_limit);
|
|
662
|
+
const used = cents(config?.used);
|
|
663
|
+
const directPercent = finitePercent(config?.creditUsagePercent ?? config?.credit_usage_percent);
|
|
664
|
+
const derivedPercent = monthlyLimit !== null && monthlyLimit > 0 && used !== null ? Math.max(0, Math.min(100, used / monthlyLimit * 100)) : null;
|
|
665
|
+
const period = currentPeriod ? {
|
|
666
|
+
type: stringOrNull(currentPeriod.type),
|
|
667
|
+
start: dateOrNull(currentPeriod.start),
|
|
668
|
+
end: dateOrNull(currentPeriod.end)
|
|
669
|
+
} : legacyPeriod(config);
|
|
670
|
+
return {
|
|
671
|
+
usedPercent: directPercent ?? derivedPercent,
|
|
672
|
+
period,
|
|
673
|
+
prepaidBalanceCents: cents(config?.prepaidBalance ?? config?.prepaid_balance),
|
|
674
|
+
onDemandCapCents: cents(config?.onDemandCap ?? config?.on_demand_cap),
|
|
675
|
+
onDemandUsedCents: cents(config?.onDemandUsed ?? config?.on_demand_used),
|
|
676
|
+
onDemandEnabled: booleanOrNull(body.onDemandEnabled ?? body.on_demand_enabled),
|
|
677
|
+
unifiedBilling: booleanOrNull(config?.isUnifiedBillingUser ?? config?.is_unified_billing_user),
|
|
678
|
+
subscriptionTier: stringOrNull(body.subscriptionTier ?? body.subscription_tier),
|
|
679
|
+
checkedAt: /* @__PURE__ */ new Date()
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
function record(value) {
|
|
683
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
684
|
+
}
|
|
685
|
+
function cents(value) {
|
|
686
|
+
if (typeof value === "number" && Number.isSafeInteger(value)) return value;
|
|
687
|
+
const object = record(value);
|
|
688
|
+
const candidate = object?.val;
|
|
689
|
+
return typeof candidate === "number" && Number.isSafeInteger(candidate) ? candidate : null;
|
|
690
|
+
}
|
|
691
|
+
function finitePercent(value) {
|
|
692
|
+
const candidate = Number(value);
|
|
693
|
+
return Number.isFinite(candidate) ? Math.max(0, Math.min(100, candidate)) : null;
|
|
694
|
+
}
|
|
695
|
+
function stringOrNull(value) {
|
|
696
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
697
|
+
}
|
|
698
|
+
function booleanOrNull(value) {
|
|
699
|
+
return typeof value === "boolean" ? value : null;
|
|
700
|
+
}
|
|
701
|
+
function dateOrNull(value) {
|
|
702
|
+
if (typeof value !== "string") return null;
|
|
703
|
+
const date = new Date(value);
|
|
704
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
705
|
+
}
|
|
706
|
+
function legacyPeriod(config) {
|
|
707
|
+
const start = dateOrNull(config?.billingPeriodStart ?? config?.billing_period_start);
|
|
708
|
+
const end = dateOrNull(config?.billingPeriodEnd ?? config?.billing_period_end);
|
|
709
|
+
return start || end ? { type: null, start, end } : null;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// src/models.ts
|
|
713
|
+
async function fetchXaiSubscriptionModels(input) {
|
|
714
|
+
const body = await fetchXaiProxyJson({
|
|
715
|
+
path: "models",
|
|
716
|
+
context: input.context,
|
|
717
|
+
...input.fetch ? { fetch: input.fetch } : {},
|
|
718
|
+
...input.timeoutMs ? { timeoutMs: input.timeoutMs } : {},
|
|
719
|
+
...input.baseUrl ? { baseUrl: input.baseUrl } : {},
|
|
720
|
+
maxBytes: 4 * 1024 * 1024,
|
|
721
|
+
label: "model metadata request"
|
|
722
|
+
});
|
|
723
|
+
const values = Array.isArray(body) ? body : body && typeof body === "object" && Array.isArray(body.data) ? body.data : [];
|
|
724
|
+
return values.flatMap((value) => {
|
|
725
|
+
const parsed = parseXaiSubscriptionModelMetadata(value);
|
|
726
|
+
return parsed ? [parsed] : [];
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
function parseXaiSubscriptionModelMetadata(value) {
|
|
730
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
731
|
+
const object = value;
|
|
732
|
+
const meta = object._meta && typeof object._meta === "object" && !Array.isArray(object._meta) ? object._meta : {};
|
|
733
|
+
const slug = firstString(object.model, object.modelId, object.id, meta.model, meta.modelId);
|
|
734
|
+
const contextWindowTokens = firstPositiveInteger(
|
|
735
|
+
object.contextWindow,
|
|
736
|
+
object.context_window,
|
|
737
|
+
meta.contextWindow,
|
|
738
|
+
meta.totalContextTokens
|
|
739
|
+
);
|
|
740
|
+
if (!slug || contextWindowTokens === null) return null;
|
|
741
|
+
const effectivePercent = firstPositiveInteger(
|
|
742
|
+
object.effectiveContextWindowPercent,
|
|
743
|
+
object.effective_context_window_percent
|
|
744
|
+
) ?? XAI_SUBSCRIPTION_EFFECTIVE_CONTEXT_PERCENT;
|
|
745
|
+
const autoCompactPercent = firstPositiveInteger(
|
|
746
|
+
object.autoCompactThresholdPercent,
|
|
747
|
+
object.auto_compact_threshold_percent
|
|
748
|
+
) ?? XAI_SUBSCRIPTION_AUTO_COMPACTION_PERCENT;
|
|
749
|
+
const backend = firstString(object.apiBackend, object.api_backend);
|
|
750
|
+
return {
|
|
751
|
+
slug,
|
|
752
|
+
name: firstString(object.name) ?? slug,
|
|
753
|
+
contextWindowTokens,
|
|
754
|
+
effectiveContextWindowTokens: Math.floor(contextWindowTokens * effectivePercent / 100),
|
|
755
|
+
autoCompactTokenLimit: Math.floor(contextWindowTokens * autoCompactPercent / 100),
|
|
756
|
+
maxCompletionTokens: firstPositiveInteger(
|
|
757
|
+
object.maxCompletionTokens,
|
|
758
|
+
object.max_completion_tokens
|
|
759
|
+
),
|
|
760
|
+
apiBackend: backend === "chat_completions" || backend === "messages" ? backend : "responses"
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
function firstString(...values) {
|
|
764
|
+
for (const value of values) {
|
|
765
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
766
|
+
}
|
|
767
|
+
return null;
|
|
768
|
+
}
|
|
769
|
+
function firstPositiveInteger(...values) {
|
|
770
|
+
for (const value of values) {
|
|
771
|
+
const number = Number(value);
|
|
772
|
+
if (Number.isSafeInteger(number) && number > 0) return number;
|
|
773
|
+
}
|
|
774
|
+
return null;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// src/images.ts
|
|
778
|
+
import { pinnedFetch as pinnedFetch2, readJsonBase64Field, readResponseTextBounded } from "@opengeni/network";
|
|
779
|
+
var XAI_IMAGE_RESPONSE_MAX_BYTES = 90 * 1024 * 1024;
|
|
780
|
+
var XAI_IMAGE_MAX_BYTES = 64 * 1024 * 1024;
|
|
781
|
+
var XAI_IMAGE_ERROR_MAX_BYTES = 64 * 1024;
|
|
782
|
+
var defaultImageFetch = async (input, init) => await pinnedFetch2(
|
|
783
|
+
input,
|
|
784
|
+
init,
|
|
785
|
+
{ environment: "production", integrationsAllowPrivateNetworkTargets: false },
|
|
786
|
+
{ label: "xAI image generation", requireHttpsOutsideLocalTest: true }
|
|
787
|
+
);
|
|
788
|
+
async function generateXaiSubscriptionImage(input) {
|
|
789
|
+
const timeoutMs = input.requestTimeoutMs ?? XAI_IMAGE_REQUEST_TIMEOUT_MS;
|
|
790
|
+
const deadline = new AbortController();
|
|
791
|
+
const timer = setTimeout(
|
|
792
|
+
() => deadline.abort(new XaiSubscriptionError("timeout", "xAI image generation timed out")),
|
|
793
|
+
timeoutMs
|
|
794
|
+
);
|
|
795
|
+
const signal = input.abortSignal ? AbortSignal.any([input.abortSignal, deadline.signal]) : deadline.signal;
|
|
796
|
+
const fetchImpl = input.fetch ?? defaultImageFetch;
|
|
797
|
+
const references = input.references ?? [];
|
|
798
|
+
if (references.length > 3) {
|
|
799
|
+
throw new XaiSubscriptionError(
|
|
800
|
+
"provider_rejected",
|
|
801
|
+
"xAI image editing supports at most three references"
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
const url = `${(input.baseUrl ?? XAI_PUBLIC_API_BASE_URL).replace(/\/+$/, "")}/images/${references.length > 0 ? "edits" : "generations"}`;
|
|
805
|
+
const request = async (token) => await fetchImpl(url, {
|
|
806
|
+
method: "POST",
|
|
807
|
+
redirect: "error",
|
|
808
|
+
headers: {
|
|
809
|
+
accept: "application/json",
|
|
810
|
+
authorization: `Bearer ${token.accessToken}`,
|
|
811
|
+
"content-type": "application/json",
|
|
812
|
+
"user-agent": `opengeni/${XAI_CLIENT_VERSION}`,
|
|
813
|
+
"x-grok-client-version": XAI_CLIENT_VERSION,
|
|
814
|
+
"x-grok-client-identifier": "opengeni",
|
|
815
|
+
...input.sessionId ? { "x-grok-session-id": input.sessionId } : {}
|
|
816
|
+
},
|
|
817
|
+
body: JSON.stringify(
|
|
818
|
+
references.length > 0 ? {
|
|
819
|
+
model: XAI_IMAGE_MODEL,
|
|
820
|
+
prompt: input.prompt,
|
|
821
|
+
n: 1,
|
|
822
|
+
resolution: "1k",
|
|
823
|
+
response_format: "b64_json",
|
|
824
|
+
...references.length === 1 ? { image: referencePayload(references[0]) } : {
|
|
825
|
+
images: references.map(referencePayload),
|
|
826
|
+
aspect_ratio: input.aspectRatio ?? "auto"
|
|
827
|
+
}
|
|
828
|
+
} : {
|
|
829
|
+
model: XAI_IMAGE_MODEL,
|
|
830
|
+
prompt: input.prompt,
|
|
831
|
+
n: 1,
|
|
832
|
+
aspect_ratio: input.aspectRatio ?? "auto",
|
|
833
|
+
resolution: "1k",
|
|
834
|
+
response_format: "b64_json"
|
|
835
|
+
}
|
|
836
|
+
),
|
|
837
|
+
signal
|
|
838
|
+
});
|
|
839
|
+
try {
|
|
840
|
+
let response = await request(await input.getToken());
|
|
841
|
+
if (response.status === 401) {
|
|
842
|
+
await response.body?.cancel().catch(() => void 0);
|
|
843
|
+
response = await request(await input.refresh());
|
|
844
|
+
}
|
|
845
|
+
if (!response.ok) {
|
|
846
|
+
const detail = await readResponseTextBounded(
|
|
847
|
+
response,
|
|
848
|
+
XAI_IMAGE_ERROR_MAX_BYTES,
|
|
849
|
+
"xAI image generation error",
|
|
850
|
+
{ signal }
|
|
851
|
+
).catch(() => "");
|
|
852
|
+
throw new XaiSubscriptionError(
|
|
853
|
+
"provider_rejected",
|
|
854
|
+
`xAI image generation failed (${response.status})${detail ? `: ${boundedMessage(detail)}` : ""}`,
|
|
855
|
+
response.status
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
const bytes = await readJsonBase64Field(response, {
|
|
859
|
+
fieldName: "b64_json",
|
|
860
|
+
shape: "string",
|
|
861
|
+
maxResponseBytes: XAI_IMAGE_RESPONSE_MAX_BYTES,
|
|
862
|
+
maxDecodedBytes: XAI_IMAGE_MAX_BYTES,
|
|
863
|
+
label: "xAI image generation",
|
|
864
|
+
signal
|
|
865
|
+
});
|
|
866
|
+
return { bytes, declaredMediaType: detectImageMediaType(bytes) };
|
|
867
|
+
} finally {
|
|
868
|
+
clearTimeout(timer);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
function referencePayload(reference) {
|
|
872
|
+
return {
|
|
873
|
+
url: `data:${reference.mediaType};base64,${Buffer.from(reference.bytes).toString("base64")}`
|
|
874
|
+
};
|
|
875
|
+
}
|
|
876
|
+
function detectImageMediaType(bytes) {
|
|
877
|
+
if (bytes.byteLength >= 8 && [137, 80, 78, 71, 13, 10, 26, 10].every((byte, index) => bytes[index] === byte)) {
|
|
878
|
+
return "image/png";
|
|
879
|
+
}
|
|
880
|
+
if (bytes.byteLength >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
|
|
881
|
+
return "image/jpeg";
|
|
882
|
+
}
|
|
883
|
+
if (bytes.byteLength >= 12 && String.fromCharCode(...bytes.subarray(0, 4)) === "RIFF" && String.fromCharCode(...bytes.subarray(8, 12)) === "WEBP") {
|
|
884
|
+
return "image/webp";
|
|
885
|
+
}
|
|
886
|
+
throw new XaiSubscriptionError("invalid_response", "xAI returned an unsupported image format");
|
|
887
|
+
}
|
|
888
|
+
function boundedMessage(body) {
|
|
889
|
+
try {
|
|
890
|
+
const value = JSON.parse(body);
|
|
891
|
+
const error = value.error && typeof value.error === "object" && !Array.isArray(value.error) ? value.error : null;
|
|
892
|
+
const message = error?.message ?? value.message;
|
|
893
|
+
if (typeof message === "string") return message.replace(/\s+/g, " ").trim().slice(0, 1e3);
|
|
894
|
+
} catch {
|
|
895
|
+
}
|
|
896
|
+
return body.replace(/\s+/g, " ").trim().slice(0, 1e3);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
// src/video.ts
|
|
900
|
+
import {
|
|
901
|
+
pinnedFetch as pinnedFetch3,
|
|
902
|
+
readResponseBodyBounded,
|
|
903
|
+
readResponseJsonBounded as readResponseJsonBounded3,
|
|
904
|
+
readResponseTextBounded as readResponseTextBounded2,
|
|
905
|
+
validateHttpUrl as validateHttpUrl2
|
|
906
|
+
} from "@opengeni/network";
|
|
907
|
+
var XAI_VIDEO_MAX_BYTES = 256 * 1024 * 1024;
|
|
908
|
+
var XAI_VIDEO_ERROR_MAX_BYTES = 64 * 1024;
|
|
909
|
+
var defaultVideoFetch = async (input, init) => await pinnedFetch3(
|
|
910
|
+
input,
|
|
911
|
+
init,
|
|
912
|
+
{
|
|
913
|
+
environment: "production",
|
|
914
|
+
integrationsAllowPrivateNetworkTargets: false
|
|
915
|
+
},
|
|
916
|
+
{ label: "xAI video generation", requireHttpsOutsideLocalTest: true }
|
|
917
|
+
);
|
|
918
|
+
async function startXaiSubscriptionVideoWithBody(input) {
|
|
919
|
+
const fetchImpl = input.fetch ?? defaultVideoFetch;
|
|
920
|
+
const baseUrl = (input.baseUrl ?? XAI_PUBLIC_API_BASE_URL).replace(/\/+$/, "");
|
|
921
|
+
const request = async (token) => await fetchWithDeadline(
|
|
922
|
+
fetchImpl,
|
|
923
|
+
`${baseUrl}/videos/generations`,
|
|
924
|
+
{
|
|
925
|
+
method: "POST",
|
|
926
|
+
redirect: "error",
|
|
927
|
+
headers: publicVideoHeaders(token, input.sessionId, true),
|
|
928
|
+
body: JSON.stringify(input.body),
|
|
929
|
+
...input.signal ? { signal: input.signal } : {}
|
|
930
|
+
},
|
|
931
|
+
XAI_VIDEO_START_TIMEOUT_MS,
|
|
932
|
+
input.signal ?? AbortSignal.timeout(XAI_VIDEO_START_TIMEOUT_MS)
|
|
933
|
+
);
|
|
934
|
+
let response = await request(await input.getToken());
|
|
935
|
+
if (response.status === 401) {
|
|
936
|
+
await response.body?.cancel().catch(() => void 0);
|
|
937
|
+
response = await request(await input.refresh());
|
|
938
|
+
}
|
|
939
|
+
if (!response.ok)
|
|
940
|
+
throw await providerError("start", response, input.signal ?? new AbortController().signal);
|
|
941
|
+
const body = await readResponseJsonBounded3(
|
|
942
|
+
response,
|
|
943
|
+
1024 * 1024,
|
|
944
|
+
"xAI video start",
|
|
945
|
+
input.signal ? { signal: input.signal } : {}
|
|
946
|
+
);
|
|
947
|
+
if (typeof body.request_id !== "string" || !body.request_id.trim()) {
|
|
948
|
+
throw new XaiSubscriptionError("invalid_response", "xAI video start response is malformed");
|
|
949
|
+
}
|
|
950
|
+
return { providerJobId: body.request_id };
|
|
951
|
+
}
|
|
952
|
+
async function getXaiSubscriptionVideoStatus(input) {
|
|
953
|
+
if (!input.providerJobId.trim() || input.providerJobId.length > 1024) {
|
|
954
|
+
throw new Error("xAI video job identity is invalid");
|
|
955
|
+
}
|
|
956
|
+
const fetchImpl = input.fetch ?? defaultVideoFetch;
|
|
957
|
+
const baseUrl = (input.baseUrl ?? XAI_PUBLIC_API_BASE_URL).replace(/\/+$/, "");
|
|
958
|
+
const request = async (token) => await fetchWithDeadline(
|
|
959
|
+
fetchImpl,
|
|
960
|
+
`${baseUrl}/videos/${encodeURIComponent(input.providerJobId)}`,
|
|
961
|
+
{
|
|
962
|
+
method: "GET",
|
|
963
|
+
redirect: "error",
|
|
964
|
+
headers: publicVideoHeaders(token, input.sessionId, false),
|
|
965
|
+
...input.signal ? { signal: input.signal } : {}
|
|
966
|
+
},
|
|
967
|
+
XAI_VIDEO_POLL_REQUEST_TIMEOUT_MS,
|
|
968
|
+
input.signal ?? AbortSignal.timeout(XAI_VIDEO_POLL_REQUEST_TIMEOUT_MS)
|
|
969
|
+
);
|
|
970
|
+
let response = await request(await input.getToken());
|
|
971
|
+
if (response.status === 401) {
|
|
972
|
+
await response.body?.cancel().catch(() => void 0);
|
|
973
|
+
response = await request(await input.refresh());
|
|
974
|
+
}
|
|
975
|
+
if (!response.ok && response.status !== 202) {
|
|
976
|
+
throw await providerError("poll", response, input.signal ?? new AbortController().signal);
|
|
977
|
+
}
|
|
978
|
+
const body = await readResponseJsonBounded3(
|
|
979
|
+
response,
|
|
980
|
+
1024 * 1024,
|
|
981
|
+
"xAI video poll",
|
|
982
|
+
input.signal ? { signal: input.signal } : {}
|
|
983
|
+
);
|
|
984
|
+
if (body.status === "pending" || body.status === "queued" || body.status === "running") {
|
|
985
|
+
return { status: "pending" };
|
|
986
|
+
}
|
|
987
|
+
if (body.status === "failed" || body.status === "expired") {
|
|
988
|
+
return {
|
|
989
|
+
status: "error",
|
|
990
|
+
publicReason: `xAI video generation ${body.status}`
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
const video = body.video && typeof body.video === "object" && !Array.isArray(body.video) ? body.video : null;
|
|
994
|
+
if (body.status !== "done" || typeof video?.url !== "string") {
|
|
995
|
+
throw new XaiSubscriptionError("invalid_response", "xAI video poll response is malformed");
|
|
996
|
+
}
|
|
997
|
+
return {
|
|
998
|
+
status: "completed",
|
|
999
|
+
outputUrl: validateMediaUrl(video.url),
|
|
1000
|
+
mediaType: "video/mp4"
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
function publicVideoHeaders(token, sessionId, json) {
|
|
1004
|
+
return new Headers({
|
|
1005
|
+
accept: "application/json",
|
|
1006
|
+
authorization: `Bearer ${token.accessToken}`,
|
|
1007
|
+
"user-agent": `opengeni/${XAI_CLIENT_VERSION}`,
|
|
1008
|
+
"x-grok-client-version": XAI_CLIENT_VERSION,
|
|
1009
|
+
"x-grok-client-identifier": "opengeni",
|
|
1010
|
+
"x-grok-client-mode": XAI_CLIENT_MODE,
|
|
1011
|
+
...sessionId ? { "x-grok-session-id": sessionId } : {},
|
|
1012
|
+
...json ? { "content-type": "application/json" } : {}
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
async function generateXaiSubscriptionVideo(input) {
|
|
1016
|
+
const baseUrl = (input.baseUrl ?? XAI_PUBLIC_API_BASE_URL).replace(/\/+$/, "");
|
|
1017
|
+
const fetchImpl = input.fetch ?? defaultVideoFetch;
|
|
1018
|
+
const deadline = new AbortController();
|
|
1019
|
+
const timeoutMs = input.generationTimeoutMs ?? XAI_VIDEO_GENERATION_TIMEOUT_MS;
|
|
1020
|
+
const timer = setTimeout(
|
|
1021
|
+
() => deadline.abort(new XaiSubscriptionError("timeout", "xAI video generation timed out")),
|
|
1022
|
+
timeoutMs
|
|
1023
|
+
);
|
|
1024
|
+
const signal = input.abortSignal ? AbortSignal.any([input.abortSignal, deadline.signal]) : deadline.signal;
|
|
1025
|
+
const references = (input.referenceImageUrls ?? []).map(validateMediaUrl);
|
|
1026
|
+
const image = input.imageUrl ? validateMediaUrl(input.imageUrl) : void 0;
|
|
1027
|
+
const request = async (token) => await fetchWithDeadline(
|
|
1028
|
+
fetchImpl,
|
|
1029
|
+
`${baseUrl}/videos/generations`,
|
|
1030
|
+
{
|
|
1031
|
+
method: "POST",
|
|
1032
|
+
redirect: "error",
|
|
1033
|
+
headers: {
|
|
1034
|
+
accept: "application/json",
|
|
1035
|
+
authorization: `Bearer ${token.accessToken}`,
|
|
1036
|
+
"content-type": "application/json"
|
|
1037
|
+
},
|
|
1038
|
+
body: JSON.stringify({
|
|
1039
|
+
model: XAI_VIDEO_MODEL,
|
|
1040
|
+
prompt: input.prompt,
|
|
1041
|
+
...image ? { image: { url: image } } : {},
|
|
1042
|
+
...references.length > 0 ? { reference_images: references.map((url) => ({ url })) } : {},
|
|
1043
|
+
...input.durationSeconds ? { duration: input.durationSeconds } : {},
|
|
1044
|
+
aspect_ratio: input.aspectRatio ?? "16:9",
|
|
1045
|
+
resolution: input.resolution ?? "480p"
|
|
1046
|
+
}),
|
|
1047
|
+
signal
|
|
1048
|
+
},
|
|
1049
|
+
XAI_VIDEO_START_TIMEOUT_MS,
|
|
1050
|
+
signal
|
|
1051
|
+
);
|
|
1052
|
+
try {
|
|
1053
|
+
let start = await request(await input.getToken());
|
|
1054
|
+
if (start.status === 401) {
|
|
1055
|
+
await start.body?.cancel().catch(() => void 0);
|
|
1056
|
+
start = await request(await input.refresh());
|
|
1057
|
+
}
|
|
1058
|
+
if (!start.ok) throw await providerError("start", start, signal);
|
|
1059
|
+
const started = await readResponseJsonBounded3(
|
|
1060
|
+
start,
|
|
1061
|
+
1024 * 1024,
|
|
1062
|
+
"xAI video start",
|
|
1063
|
+
{ signal }
|
|
1064
|
+
);
|
|
1065
|
+
const requestId = typeof started.request_id === "string" && started.request_id.length > 0 ? started.request_id : null;
|
|
1066
|
+
if (!requestId) {
|
|
1067
|
+
throw new XaiSubscriptionError(
|
|
1068
|
+
"invalid_response",
|
|
1069
|
+
"xAI video generation did not return request_id"
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
const sleep = input.sleep ?? abortableSleep;
|
|
1073
|
+
for (; ; ) {
|
|
1074
|
+
await sleep(XAI_VIDEO_POLL_INTERVAL_MS, signal);
|
|
1075
|
+
let poll = await pollVideo(fetchImpl, baseUrl, requestId, await input.getToken(), signal);
|
|
1076
|
+
if (poll.status === 401) {
|
|
1077
|
+
await poll.body?.cancel().catch(() => void 0);
|
|
1078
|
+
poll = await pollVideo(fetchImpl, baseUrl, requestId, await input.refresh(), signal);
|
|
1079
|
+
}
|
|
1080
|
+
if (!poll.ok && poll.status !== 202) throw await providerError("poll", poll, signal);
|
|
1081
|
+
const status = await readResponseJsonBounded3(
|
|
1082
|
+
poll,
|
|
1083
|
+
1024 * 1024,
|
|
1084
|
+
"xAI video poll",
|
|
1085
|
+
{ signal }
|
|
1086
|
+
);
|
|
1087
|
+
if (status.status === "failed" || status.status === "expired") {
|
|
1088
|
+
throw new XaiSubscriptionError(
|
|
1089
|
+
"provider_rejected",
|
|
1090
|
+
`xAI video generation ${status.status}`
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
if (status.status !== "done") continue;
|
|
1094
|
+
const video = status.video && typeof status.video === "object" && !Array.isArray(status.video) ? status.video : null;
|
|
1095
|
+
const downloadUrl = typeof video?.url === "string" ? validateMediaUrl(video.url) : null;
|
|
1096
|
+
if (!downloadUrl) {
|
|
1097
|
+
throw new XaiSubscriptionError(
|
|
1098
|
+
"invalid_response",
|
|
1099
|
+
"xAI video generation completed without a download URL"
|
|
1100
|
+
);
|
|
1101
|
+
}
|
|
1102
|
+
const download = await fetchWithDeadline(
|
|
1103
|
+
fetchImpl,
|
|
1104
|
+
downloadUrl,
|
|
1105
|
+
{ method: "GET", redirect: "error", signal },
|
|
1106
|
+
XAI_VIDEO_DOWNLOAD_TIMEOUT_MS,
|
|
1107
|
+
signal
|
|
1108
|
+
);
|
|
1109
|
+
if (!download.ok) throw await providerError("download", download, signal);
|
|
1110
|
+
const bytes = await readResponseBodyBounded(
|
|
1111
|
+
download,
|
|
1112
|
+
XAI_VIDEO_MAX_BYTES,
|
|
1113
|
+
"xAI video download",
|
|
1114
|
+
{ signal }
|
|
1115
|
+
);
|
|
1116
|
+
return { bytes, declaredMediaType: "video/mp4", requestId };
|
|
1117
|
+
}
|
|
1118
|
+
} finally {
|
|
1119
|
+
clearTimeout(timer);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
async function pollVideo(fetchImpl, baseUrl, requestId, token, signal) {
|
|
1123
|
+
return await fetchWithDeadline(
|
|
1124
|
+
fetchImpl,
|
|
1125
|
+
`${baseUrl}/videos/${encodeURIComponent(requestId)}`,
|
|
1126
|
+
{
|
|
1127
|
+
method: "GET",
|
|
1128
|
+
redirect: "error",
|
|
1129
|
+
headers: {
|
|
1130
|
+
accept: "application/json",
|
|
1131
|
+
authorization: `Bearer ${token.accessToken}`
|
|
1132
|
+
},
|
|
1133
|
+
signal
|
|
1134
|
+
},
|
|
1135
|
+
XAI_VIDEO_POLL_REQUEST_TIMEOUT_MS,
|
|
1136
|
+
signal
|
|
1137
|
+
);
|
|
1138
|
+
}
|
|
1139
|
+
async function fetchWithDeadline(fetchImpl, url, init, timeoutMs, outerSignal) {
|
|
1140
|
+
const timeout = AbortSignal.timeout(timeoutMs);
|
|
1141
|
+
return await fetchImpl(url, {
|
|
1142
|
+
...init,
|
|
1143
|
+
signal: AbortSignal.any([outerSignal, timeout])
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
async function providerError(phase, response, signal) {
|
|
1147
|
+
const detail = await readResponseTextBounded2(
|
|
1148
|
+
response,
|
|
1149
|
+
XAI_VIDEO_ERROR_MAX_BYTES,
|
|
1150
|
+
`xAI video ${phase} error`,
|
|
1151
|
+
{ signal }
|
|
1152
|
+
).catch(() => "");
|
|
1153
|
+
return new XaiSubscriptionError(
|
|
1154
|
+
"provider_rejected",
|
|
1155
|
+
`xAI video ${phase} failed (${response.status})${detail ? `: ${detail.replace(/\s+/g, " ").trim().slice(0, 1e3)}` : ""}`,
|
|
1156
|
+
response.status
|
|
1157
|
+
);
|
|
1158
|
+
}
|
|
1159
|
+
function validateMediaUrl(value) {
|
|
1160
|
+
try {
|
|
1161
|
+
return validateHttpUrl2(value, { label: "xAI media" });
|
|
1162
|
+
} catch {
|
|
1163
|
+
throw new XaiSubscriptionError("invalid_response", "xAI returned an invalid media URL");
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
async function abortableSleep(ms, signal) {
|
|
1167
|
+
if (signal.aborted) throw signal.reason;
|
|
1168
|
+
await new Promise((resolve, reject) => {
|
|
1169
|
+
const timer = setTimeout(done, ms);
|
|
1170
|
+
const onAbort = () => done(signal.reason);
|
|
1171
|
+
function done(error) {
|
|
1172
|
+
clearTimeout(timer);
|
|
1173
|
+
signal.removeEventListener("abort", onAbort);
|
|
1174
|
+
if (error === void 0) {
|
|
1175
|
+
resolve();
|
|
1176
|
+
} else {
|
|
1177
|
+
reject(error);
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1181
|
+
});
|
|
1182
|
+
}
|
|
1183
|
+
export {
|
|
1184
|
+
XAI_CLIENT_MODE,
|
|
1185
|
+
XAI_CLIENT_VERSION,
|
|
1186
|
+
XAI_DEVICE_AUTHORIZATION_URL,
|
|
1187
|
+
XAI_DEVICE_CODE_GRANT_TYPE,
|
|
1188
|
+
XAI_IMAGE_MODEL,
|
|
1189
|
+
XAI_IMAGE_REQUEST_TIMEOUT_MS,
|
|
1190
|
+
XAI_OAUTH_CLIENT_ID,
|
|
1191
|
+
XAI_OAUTH_ISSUER,
|
|
1192
|
+
XAI_OAUTH_OPERATION_TIMEOUT_MS,
|
|
1193
|
+
XAI_OAUTH_SCOPES,
|
|
1194
|
+
XAI_PUBLIC_API_BASE_URL,
|
|
1195
|
+
XAI_REFRESH_FALLBACK_MS,
|
|
1196
|
+
XAI_REFRESH_WINDOW_MS,
|
|
1197
|
+
XAI_RESPONSE_SDK_OUTER_TIMEOUT_MS,
|
|
1198
|
+
XAI_SUBSCRIPTION_AUTO_COMPACTION_PERCENT,
|
|
1199
|
+
XAI_SUBSCRIPTION_EFFECTIVE_CONTEXT_PERCENT,
|
|
1200
|
+
XAI_SUBSCRIPTION_MODEL_AUTO_COMPACT_TOKEN_LIMIT,
|
|
1201
|
+
XAI_SUBSCRIPTION_MODEL_CONTEXT_WINDOW_TOKENS,
|
|
1202
|
+
XAI_SUBSCRIPTION_MODEL_EFFECTIVE_CONTEXT_WINDOW_TOKENS,
|
|
1203
|
+
XAI_SUBSCRIPTION_MODEL_ID_PREFIX,
|
|
1204
|
+
XAI_SUBSCRIPTION_MODEL_SLUGS,
|
|
1205
|
+
XAI_SUBSCRIPTION_PROVIDER_ID,
|
|
1206
|
+
XAI_SUBSCRIPTION_PROXY_BASE_URL,
|
|
1207
|
+
XAI_SUBSCRIPTION_REQUEST_BODY_NORMALIZED_HEADER,
|
|
1208
|
+
XAI_SUBSCRIPTION_REQUEST_ID_HEADER,
|
|
1209
|
+
XAI_SUBSCRIPTION_REQUEST_MODEL_HEADER,
|
|
1210
|
+
XAI_SUBSCRIPTION_TRANSPORT_ERROR_HEADER,
|
|
1211
|
+
XAI_TOKEN_AUTH_HEADER_VALUE,
|
|
1212
|
+
XAI_TOKEN_URL,
|
|
1213
|
+
XAI_USERINFO_URL,
|
|
1214
|
+
XAI_VIDEO_DOWNLOAD_TIMEOUT_MS,
|
|
1215
|
+
XAI_VIDEO_GENERATION_TIMEOUT_MS,
|
|
1216
|
+
XAI_VIDEO_MODEL,
|
|
1217
|
+
XAI_VIDEO_POLL_INTERVAL_MS,
|
|
1218
|
+
XAI_VIDEO_POLL_REQUEST_TIMEOUT_MS,
|
|
1219
|
+
XAI_VIDEO_START_TIMEOUT_MS,
|
|
1220
|
+
XaiSubscriptionError,
|
|
1221
|
+
XaiSubscriptionReloginRequired,
|
|
1222
|
+
XaiSubscriptionTransientError,
|
|
1223
|
+
decodeXaiJwtPayload,
|
|
1224
|
+
fetchXaiProxyJson,
|
|
1225
|
+
fetchXaiSubscriptionModels,
|
|
1226
|
+
fetchXaiSubscriptionQuota,
|
|
1227
|
+
fetchXaiVerifiedIdentity,
|
|
1228
|
+
generateXaiSubscriptionImage,
|
|
1229
|
+
generateXaiSubscriptionVideo,
|
|
1230
|
+
getXaiSubscriptionVideoStatus,
|
|
1231
|
+
isXaiSubscriptionTransportError,
|
|
1232
|
+
normalizeXaiResponseEventJson,
|
|
1233
|
+
normalizeXaiSubscriptionRequestBody,
|
|
1234
|
+
parseXaiSubscriptionModelMetadata,
|
|
1235
|
+
pollXaiDeviceCode,
|
|
1236
|
+
refreshXaiToken,
|
|
1237
|
+
requestXaiDeviceCode,
|
|
1238
|
+
runBoundedXaiOperation,
|
|
1239
|
+
startXaiSubscriptionVideoWithBody,
|
|
1240
|
+
xaiAccessTokenExpiry,
|
|
1241
|
+
xaiSubscriptionFetch,
|
|
1242
|
+
xaiSubscriptionProxyHeaders,
|
|
1243
|
+
xaiSubscriptionRequestStorage
|
|
1244
|
+
};
|
|
1245
|
+
//# sourceMappingURL=index.js.map
|