@resultdev/sdk 0.3.0 → 0.3.2
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/CHANGELOG.md +20 -0
- package/dist/{client-CJv_awPt.d.cts → client-D5IGLPW4.d.ts} +5 -3
- package/dist/{client-DrsZ1qIm.d.ts → client-N6MW9IE1.d.cts} +5 -3
- package/dist/index.cjs +116 -21
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +116 -21
- package/dist/{middleware-BJl9JRg3.d.ts → middleware-8UNqItQG.d.ts} +1 -1
- package/dist/{middleware-C1Z6aMvn.d.cts → middleware-CGn44ocX.d.cts} +1 -1
- package/dist/ssr/middleware.d.cts +2 -2
- package/dist/ssr/middleware.d.ts +2 -2
- package/dist/ssr.cjs +116 -21
- package/dist/ssr.d.cts +4 -4
- package/dist/ssr.d.ts +4 -4
- package/dist/ssr.js +116 -21
- package/dist/{types-DSVtGaIA.d.cts → types-BTdjI7Yj.d.cts} +4 -2
- package/dist/{types-DSVtGaIA.d.ts → types-BTdjI7Yj.d.ts} +4 -2
- package/package.json +13 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @resultdev/sdk
|
|
2
2
|
|
|
3
|
+
## 0.3.2
|
|
4
|
+
|
|
5
|
+
- AI calls made through the SDK now report returned token usage to the
|
|
6
|
+
matching Result app. Operations can show per-app AI usage even while the
|
|
7
|
+
upstream partnership AI counters remain unavailable.
|
|
8
|
+
- Caller AbortSignal listeners are now detached once a response body is
|
|
9
|
+
fully consumed, instead of accumulating on long-lived signals across
|
|
10
|
+
requests.
|
|
11
|
+
|
|
12
|
+
## 0.3.1
|
|
13
|
+
|
|
14
|
+
- A missing `baseUrl` now throws `MISSING_BASE_URL` at client construction
|
|
15
|
+
instead of silently falling back to a localhost dev URL. The fallback made
|
|
16
|
+
deployed sites whose `NEXT_PUBLIC_BACKEND_URL` was undefined in the
|
|
17
|
+
browser bundle (for example when the env var is read through an imported
|
|
18
|
+
`process` module, which defeats build-time inlining) call `localhost` from
|
|
19
|
+
production pages, which surfaced as Chrome's "access other apps and
|
|
20
|
+
services on this device" permission prompt. The error's fix hint names the
|
|
21
|
+
env var and the inlining rule.
|
|
22
|
+
|
|
3
23
|
## 0.3.0
|
|
4
24
|
|
|
5
25
|
Reliability release: every fix here comes from live verification against a
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { e as AuthSession, U as UserSchema, a as ResultConfig, G as AuthRefreshResponse, C as ChatCompletionRequest, B as ToolCall, H as Annotation, I as ImageGenerationRequest, j as EmbeddingsRequest, J as EmbeddingObject, h as CreateUserRequest, K as CreateUserResponse, o as ResultError, g as CreateSessionRequest, L as CreateSessionResponse, l as OAuthProvidersSchema, M as RefreshSessionResponse, N as GetProfileResponse, Q as SendVerificationEmailRequest, V as VerifyEmailRequest, W as VerifyEmailResponse, X as SendResetPasswordEmailRequest, Y as ExchangeResetPasswordTokenRequest, Z as ExchangeResetPasswordTokenResponse, _ as ResetPasswordResponse, $ as GetPublicAuthConfigResponse, S as SendRawEmailRequest, q as SendEmailResponse, v as SubscribeResponse, r as SocketMessage, P as PresenceMember, u as StorageFileSchema, a0 as ListObjectsResponseSchema, i as DeleteObjectsResponse, A as Analytics, w as Support } from './types-
|
|
1
|
+
import { e as AuthSession, U as UserSchema, a as ResultConfig, G as AuthRefreshResponse, C as ChatCompletionRequest, B as ToolCall, H as Annotation, I as ImageGenerationRequest, j as EmbeddingsRequest, J as EmbeddingObject, h as CreateUserRequest, K as CreateUserResponse, o as ResultError, g as CreateSessionRequest, L as CreateSessionResponse, l as OAuthProvidersSchema, M as RefreshSessionResponse, N as GetProfileResponse, Q as SendVerificationEmailRequest, V as VerifyEmailRequest, W as VerifyEmailResponse, X as SendResetPasswordEmailRequest, Y as ExchangeResetPasswordTokenRequest, Z as ExchangeResetPasswordTokenResponse, _ as ResetPasswordResponse, $ as GetPublicAuthConfigResponse, S as SendRawEmailRequest, q as SendEmailResponse, v as SubscribeResponse, r as SocketMessage, P as PresenceMember, u as StorageFileSchema, a0 as ListObjectsResponseSchema, i as DeleteObjectsResponse, A as Analytics, w as Support } from './types-BTdjI7Yj.js';
|
|
2
2
|
import * as _supabase_postgrest_js from '@supabase/postgrest-js';
|
|
3
3
|
import { PostgrestClient } from '@supabase/postgrest-js';
|
|
4
4
|
|
|
@@ -200,6 +200,8 @@ declare class HttpClient {
|
|
|
200
200
|
setRefreshToken(token: string | null): void;
|
|
201
201
|
/** Returns the current default headers including the authorization header if set. */
|
|
202
202
|
getHeaders(): Record<string, string>;
|
|
203
|
+
/** Returns the publishable project key used to identify SDK usage reports. */
|
|
204
|
+
getAnonKey(): string | undefined;
|
|
203
205
|
refreshAccessToken(): Promise<AuthRefreshResponse>;
|
|
204
206
|
/** Returns a token safe to use for a new connection handshake. */
|
|
205
207
|
getValidAccessToken(leewaySeconds?: number): Promise<string | null>;
|
|
@@ -996,7 +998,7 @@ type AccessTokenChangeEvent = typeof AuthChangeEvent.SIGNED_IN | typeof AuthChan
|
|
|
996
998
|
* import { ResultClient } from '@resultdev/sdk';
|
|
997
999
|
*
|
|
998
1000
|
* const client = new ResultClient({
|
|
999
|
-
* baseUrl:
|
|
1001
|
+
* baseUrl: process.env.NEXT_PUBLIC_BACKEND_URL!
|
|
1000
1002
|
* });
|
|
1001
1003
|
*
|
|
1002
1004
|
* // Authentication
|
|
@@ -1027,7 +1029,7 @@ type AccessTokenChangeEvent = typeof AuthChangeEvent.SIGNED_IN | typeof AuthChan
|
|
|
1027
1029
|
*
|
|
1028
1030
|
* // Enable debug logging
|
|
1029
1031
|
* const debugClient = new ResultClient({
|
|
1030
|
-
* baseUrl:
|
|
1032
|
+
* baseUrl: process.env.NEXT_PUBLIC_BACKEND_URL!,
|
|
1031
1033
|
* debug: true
|
|
1032
1034
|
* });
|
|
1033
1035
|
* ```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { e as AuthSession, U as UserSchema, a as ResultConfig, G as AuthRefreshResponse, C as ChatCompletionRequest, B as ToolCall, H as Annotation, I as ImageGenerationRequest, j as EmbeddingsRequest, J as EmbeddingObject, h as CreateUserRequest, K as CreateUserResponse, o as ResultError, g as CreateSessionRequest, L as CreateSessionResponse, l as OAuthProvidersSchema, M as RefreshSessionResponse, N as GetProfileResponse, Q as SendVerificationEmailRequest, V as VerifyEmailRequest, W as VerifyEmailResponse, X as SendResetPasswordEmailRequest, Y as ExchangeResetPasswordTokenRequest, Z as ExchangeResetPasswordTokenResponse, _ as ResetPasswordResponse, $ as GetPublicAuthConfigResponse, S as SendRawEmailRequest, q as SendEmailResponse, v as SubscribeResponse, r as SocketMessage, P as PresenceMember, u as StorageFileSchema, a0 as ListObjectsResponseSchema, i as DeleteObjectsResponse, A as Analytics, w as Support } from './types-
|
|
1
|
+
import { e as AuthSession, U as UserSchema, a as ResultConfig, G as AuthRefreshResponse, C as ChatCompletionRequest, B as ToolCall, H as Annotation, I as ImageGenerationRequest, j as EmbeddingsRequest, J as EmbeddingObject, h as CreateUserRequest, K as CreateUserResponse, o as ResultError, g as CreateSessionRequest, L as CreateSessionResponse, l as OAuthProvidersSchema, M as RefreshSessionResponse, N as GetProfileResponse, Q as SendVerificationEmailRequest, V as VerifyEmailRequest, W as VerifyEmailResponse, X as SendResetPasswordEmailRequest, Y as ExchangeResetPasswordTokenRequest, Z as ExchangeResetPasswordTokenResponse, _ as ResetPasswordResponse, $ as GetPublicAuthConfigResponse, S as SendRawEmailRequest, q as SendEmailResponse, v as SubscribeResponse, r as SocketMessage, P as PresenceMember, u as StorageFileSchema, a0 as ListObjectsResponseSchema, i as DeleteObjectsResponse, A as Analytics, w as Support } from './types-BTdjI7Yj.cjs';
|
|
2
2
|
import * as _supabase_postgrest_js from '@supabase/postgrest-js';
|
|
3
3
|
import { PostgrestClient } from '@supabase/postgrest-js';
|
|
4
4
|
|
|
@@ -200,6 +200,8 @@ declare class HttpClient {
|
|
|
200
200
|
setRefreshToken(token: string | null): void;
|
|
201
201
|
/** Returns the current default headers including the authorization header if set. */
|
|
202
202
|
getHeaders(): Record<string, string>;
|
|
203
|
+
/** Returns the publishable project key used to identify SDK usage reports. */
|
|
204
|
+
getAnonKey(): string | undefined;
|
|
203
205
|
refreshAccessToken(): Promise<AuthRefreshResponse>;
|
|
204
206
|
/** Returns a token safe to use for a new connection handshake. */
|
|
205
207
|
getValidAccessToken(leewaySeconds?: number): Promise<string | null>;
|
|
@@ -996,7 +998,7 @@ type AccessTokenChangeEvent = typeof AuthChangeEvent.SIGNED_IN | typeof AuthChan
|
|
|
996
998
|
* import { ResultClient } from '@resultdev/sdk';
|
|
997
999
|
*
|
|
998
1000
|
* const client = new ResultClient({
|
|
999
|
-
* baseUrl:
|
|
1001
|
+
* baseUrl: process.env.NEXT_PUBLIC_BACKEND_URL!
|
|
1000
1002
|
* });
|
|
1001
1003
|
*
|
|
1002
1004
|
* // Authentication
|
|
@@ -1027,7 +1029,7 @@ type AccessTokenChangeEvent = typeof AuthChangeEvent.SIGNED_IN | typeof AuthChan
|
|
|
1027
1029
|
*
|
|
1028
1030
|
* // Enable debug logging
|
|
1029
1031
|
* const debugClient = new ResultClient({
|
|
1030
|
-
* baseUrl:
|
|
1032
|
+
* baseUrl: process.env.NEXT_PUBLIC_BACKEND_URL!,
|
|
1031
1033
|
* debug: true
|
|
1032
1034
|
* });
|
|
1033
1035
|
* ```
|
package/dist/index.cjs
CHANGED
|
@@ -503,7 +503,15 @@ var HttpClient = class {
|
|
|
503
503
|
*/
|
|
504
504
|
constructor(config, tokenManager, logger) {
|
|
505
505
|
this.config = config;
|
|
506
|
-
|
|
506
|
+
if (!config.baseUrl) {
|
|
507
|
+
throw new ResultError(
|
|
508
|
+
"createClient needs a baseUrl, but it was undefined at runtime.",
|
|
509
|
+
0,
|
|
510
|
+
"MISSING_BASE_URL",
|
|
511
|
+
"Pass the NEXT_PUBLIC_BACKEND_URL value from .env.local. In browser code, write process.env.NEXT_PUBLIC_BACKEND_URL as a literal expression (never through an imported process module) so the bundler inlines it, and set it as a deployments build variable before deploying."
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
this.baseUrl = config.baseUrl;
|
|
507
515
|
this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
|
|
508
516
|
this.anonKey = config.anonKey;
|
|
509
517
|
this.defaultHeaders = {
|
|
@@ -594,6 +602,7 @@ var HttpClient = class {
|
|
|
594
602
|
}
|
|
595
603
|
let controller;
|
|
596
604
|
let timer;
|
|
605
|
+
let removeCallerAbortListener;
|
|
597
606
|
if (this.timeout > 0 || callerSignal) {
|
|
598
607
|
controller = new AbortController();
|
|
599
608
|
if (this.timeout > 0) {
|
|
@@ -607,16 +616,11 @@ var HttpClient = class {
|
|
|
607
616
|
callerSignal.addEventListener("abort", onCallerAbort, {
|
|
608
617
|
once: true
|
|
609
618
|
});
|
|
610
|
-
|
|
611
|
-
"abort",
|
|
612
|
-
() => {
|
|
613
|
-
callerSignal.removeEventListener("abort", onCallerAbort);
|
|
614
|
-
},
|
|
615
|
-
{ once: true }
|
|
616
|
-
);
|
|
619
|
+
removeCallerAbortListener = () => callerSignal.removeEventListener("abort", onCallerAbort);
|
|
617
620
|
}
|
|
618
621
|
}
|
|
619
622
|
}
|
|
623
|
+
let detachOnExit = true;
|
|
620
624
|
try {
|
|
621
625
|
const response = await this.fetch(url, {
|
|
622
626
|
method,
|
|
@@ -637,14 +641,9 @@ var HttpClient = class {
|
|
|
637
641
|
);
|
|
638
642
|
continue;
|
|
639
643
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
}
|
|
643
|
-
return response;
|
|
644
|
+
detachOnExit = false;
|
|
645
|
+
return { response, releaseCallerSignal: removeCallerAbortListener };
|
|
644
646
|
} catch (err) {
|
|
645
|
-
if (timer !== void 0) {
|
|
646
|
-
clearTimeout(timer);
|
|
647
|
-
}
|
|
648
647
|
if (err?.name === "AbortError") {
|
|
649
648
|
if (controller?.signal.aborted && this.timeout > 0 && !callerSignal?.aborted) {
|
|
650
649
|
throw new ResultError(
|
|
@@ -664,6 +663,13 @@ var HttpClient = class {
|
|
|
664
663
|
0,
|
|
665
664
|
"NETWORK_ERROR"
|
|
666
665
|
);
|
|
666
|
+
} finally {
|
|
667
|
+
if (timer !== void 0) {
|
|
668
|
+
clearTimeout(timer);
|
|
669
|
+
}
|
|
670
|
+
if (detachOnExit) {
|
|
671
|
+
removeCallerAbortListener?.();
|
|
672
|
+
}
|
|
667
673
|
}
|
|
668
674
|
}
|
|
669
675
|
throw lastError || new ResultError(
|
|
@@ -726,7 +732,7 @@ var HttpClient = class {
|
|
|
726
732
|
});
|
|
727
733
|
}
|
|
728
734
|
this.logger.logRequest(method, url, requestHeaders, processedBody);
|
|
729
|
-
const response = await this.fetchWithRetry({
|
|
735
|
+
const { response, releaseCallerSignal } = await this.fetchWithRetry({
|
|
730
736
|
method,
|
|
731
737
|
url,
|
|
732
738
|
headers: requestHeaders,
|
|
@@ -749,6 +755,8 @@ var HttpClient = class {
|
|
|
749
755
|
);
|
|
750
756
|
}
|
|
751
757
|
throw err;
|
|
758
|
+
} finally {
|
|
759
|
+
releaseCallerSignal?.();
|
|
752
760
|
}
|
|
753
761
|
this.logger.logResponse(
|
|
754
762
|
method,
|
|
@@ -850,7 +858,7 @@ var HttpClient = class {
|
|
|
850
858
|
const callerSignal = initSignal ?? request?.signal;
|
|
851
859
|
const maxAttempts = IDEMPOTENT_METHODS.has(method.toUpperCase()) ? this.retryCount : 0;
|
|
852
860
|
this.logger.logRequest(method, url, requestHeaders, body);
|
|
853
|
-
const response = await this.fetchWithRetry({
|
|
861
|
+
const { response } = await this.fetchWithRetry({
|
|
854
862
|
method,
|
|
855
863
|
url,
|
|
856
864
|
headers: requestHeaders,
|
|
@@ -951,6 +959,10 @@ var HttpClient = class {
|
|
|
951
959
|
}
|
|
952
960
|
return headers;
|
|
953
961
|
}
|
|
962
|
+
/** Returns the publishable project key used to identify SDK usage reports. */
|
|
963
|
+
getAnonKey() {
|
|
964
|
+
return this.anonKey;
|
|
965
|
+
}
|
|
954
966
|
async refreshAccessToken() {
|
|
955
967
|
if (this.isRefreshing) {
|
|
956
968
|
return this.refreshPromise;
|
|
@@ -1020,6 +1032,47 @@ var HttpClient = class {
|
|
|
1020
1032
|
}
|
|
1021
1033
|
};
|
|
1022
1034
|
|
|
1035
|
+
// src/modules/ai-usage.ts
|
|
1036
|
+
var USAGE_ENDPOINT = "https://beta.result.dev/api/usage/ai";
|
|
1037
|
+
async function reportAiUsage(http, requestId, model, kind, tokens) {
|
|
1038
|
+
const anonKey = http.getAnonKey();
|
|
1039
|
+
if (!anonKey || !Number.isSafeInteger(tokens) || tokens <= 0) {
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
const controller = new AbortController();
|
|
1043
|
+
const timeout = setTimeout(() => controller.abort(), 2e3);
|
|
1044
|
+
try {
|
|
1045
|
+
const request = {
|
|
1046
|
+
method: "POST",
|
|
1047
|
+
headers: { "content-type": "application/json" },
|
|
1048
|
+
body: JSON.stringify({
|
|
1049
|
+
requestId,
|
|
1050
|
+
backendUrl: http.baseUrl,
|
|
1051
|
+
anonKey,
|
|
1052
|
+
model,
|
|
1053
|
+
kind,
|
|
1054
|
+
tokens
|
|
1055
|
+
}),
|
|
1056
|
+
keepalive: true,
|
|
1057
|
+
signal: controller.signal
|
|
1058
|
+
};
|
|
1059
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
1060
|
+
try {
|
|
1061
|
+
const response = await http.fetch(USAGE_ENDPOINT, request);
|
|
1062
|
+
if (response.status < 500) return;
|
|
1063
|
+
} catch {
|
|
1064
|
+
if (controller.signal.aborted) return;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
} catch {
|
|
1068
|
+
} finally {
|
|
1069
|
+
clearTimeout(timeout);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
function aiUsageRequestId() {
|
|
1073
|
+
return globalThis.crypto?.randomUUID?.() ?? null;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1023
1076
|
// src/modules/ai.ts
|
|
1024
1077
|
var SUPPORTED_AUDIO_FORMATS = [
|
|
1025
1078
|
"wav",
|
|
@@ -1107,6 +1160,7 @@ var ChatCompletions = class {
|
|
|
1107
1160
|
}
|
|
1108
1161
|
http;
|
|
1109
1162
|
async create(params) {
|
|
1163
|
+
const usageRequestId = aiUsageRequestId();
|
|
1110
1164
|
const contentSummary = summarizeContent(params.messages ?? []);
|
|
1111
1165
|
assertSupportedContent(params.model, contentSummary);
|
|
1112
1166
|
const backendParams = {
|
|
@@ -1151,7 +1205,7 @@ var ChatCompletions = class {
|
|
|
1151
1205
|
contentSummary
|
|
1152
1206
|
);
|
|
1153
1207
|
}
|
|
1154
|
-
return this.parseSSEStream(response2, params.model);
|
|
1208
|
+
return this.parseSSEStream(response2, params.model, usageRequestId);
|
|
1155
1209
|
}
|
|
1156
1210
|
let response;
|
|
1157
1211
|
try {
|
|
@@ -1160,6 +1214,16 @@ var ChatCompletions = class {
|
|
|
1160
1214
|
throw enrichUpstreamError(error, contentSummary);
|
|
1161
1215
|
}
|
|
1162
1216
|
const content = response.text || "";
|
|
1217
|
+
const totalTokens = response.metadata?.usage?.totalTokens || 0;
|
|
1218
|
+
if (usageRequestId) {
|
|
1219
|
+
await reportAiUsage(
|
|
1220
|
+
this.http,
|
|
1221
|
+
usageRequestId,
|
|
1222
|
+
params.model,
|
|
1223
|
+
"chat",
|
|
1224
|
+
totalTokens
|
|
1225
|
+
);
|
|
1226
|
+
}
|
|
1163
1227
|
return {
|
|
1164
1228
|
id: `chatcmpl-${Date.now()}`,
|
|
1165
1229
|
object: "chat.completion",
|
|
@@ -1186,14 +1250,14 @@ var ChatCompletions = class {
|
|
|
1186
1250
|
usage: {
|
|
1187
1251
|
prompt_tokens: response.metadata?.usage?.promptTokens || 0,
|
|
1188
1252
|
completion_tokens: response.metadata?.usage?.completionTokens || 0,
|
|
1189
|
-
total_tokens:
|
|
1253
|
+
total_tokens: totalTokens
|
|
1190
1254
|
}
|
|
1191
1255
|
};
|
|
1192
1256
|
}
|
|
1193
1257
|
/**
|
|
1194
1258
|
* Parse SSE stream into async iterable of OpenAI-like chunks
|
|
1195
1259
|
*/
|
|
1196
|
-
async *parseSSEStream(response, model) {
|
|
1260
|
+
async *parseSSEStream(response, model, usageRequestId) {
|
|
1197
1261
|
const reader = response.body?.getReader();
|
|
1198
1262
|
if (!reader) {
|
|
1199
1263
|
throw new ResultError(
|
|
@@ -1271,6 +1335,15 @@ var ChatCompletions = class {
|
|
|
1271
1335
|
};
|
|
1272
1336
|
}
|
|
1273
1337
|
if (data.tokenUsage) {
|
|
1338
|
+
if (usageRequestId) {
|
|
1339
|
+
await reportAiUsage(
|
|
1340
|
+
this.http,
|
|
1341
|
+
usageRequestId,
|
|
1342
|
+
model,
|
|
1343
|
+
"chat",
|
|
1344
|
+
data.tokenUsage.totalTokens || 0
|
|
1345
|
+
);
|
|
1346
|
+
}
|
|
1274
1347
|
yield {
|
|
1275
1348
|
id: `chatcmpl-${Date.now()}`,
|
|
1276
1349
|
object: "chat.completion.chunk",
|
|
@@ -1342,17 +1415,28 @@ var Embeddings = class {
|
|
|
1342
1415
|
* ```
|
|
1343
1416
|
*/
|
|
1344
1417
|
async create(params) {
|
|
1418
|
+
const usageRequestId = aiUsageRequestId();
|
|
1345
1419
|
const response = await this.http.post(
|
|
1346
1420
|
"/api/ai/embeddings",
|
|
1347
1421
|
params
|
|
1348
1422
|
);
|
|
1423
|
+
const totalTokens = response.metadata?.usage?.totalTokens || 0;
|
|
1424
|
+
if (usageRequestId) {
|
|
1425
|
+
await reportAiUsage(
|
|
1426
|
+
this.http,
|
|
1427
|
+
usageRequestId,
|
|
1428
|
+
params.model,
|
|
1429
|
+
"embeddings",
|
|
1430
|
+
totalTokens
|
|
1431
|
+
);
|
|
1432
|
+
}
|
|
1349
1433
|
return {
|
|
1350
1434
|
object: response.object,
|
|
1351
1435
|
data: response.data,
|
|
1352
1436
|
model: response.metadata?.model,
|
|
1353
1437
|
usage: response.metadata?.usage ? {
|
|
1354
1438
|
prompt_tokens: response.metadata.usage.promptTokens || 0,
|
|
1355
|
-
total_tokens:
|
|
1439
|
+
total_tokens: totalTokens
|
|
1356
1440
|
} : {
|
|
1357
1441
|
prompt_tokens: 0,
|
|
1358
1442
|
total_tokens: 0
|
|
@@ -1390,6 +1474,7 @@ var Images = class {
|
|
|
1390
1474
|
* ```
|
|
1391
1475
|
*/
|
|
1392
1476
|
async generate(params) {
|
|
1477
|
+
const usageRequestId = aiUsageRequestId();
|
|
1393
1478
|
const response = await this.http.post(
|
|
1394
1479
|
"/api/ai/image/generation",
|
|
1395
1480
|
params
|
|
@@ -1403,6 +1488,16 @@ var Images = class {
|
|
|
1403
1488
|
} else if (response.text) {
|
|
1404
1489
|
data = [{ content: response.text }];
|
|
1405
1490
|
}
|
|
1491
|
+
const totalTokens = response.metadata?.usage?.totalTokens || 0;
|
|
1492
|
+
if (usageRequestId) {
|
|
1493
|
+
await reportAiUsage(
|
|
1494
|
+
this.http,
|
|
1495
|
+
usageRequestId,
|
|
1496
|
+
params.model,
|
|
1497
|
+
"image",
|
|
1498
|
+
totalTokens
|
|
1499
|
+
);
|
|
1500
|
+
}
|
|
1406
1501
|
return {
|
|
1407
1502
|
created: Math.floor(Date.now() / 1e3),
|
|
1408
1503
|
data,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { R as ResultClient } from './client-
|
|
2
|
-
export { A as AI, a as AccessTokenChangeEvent, b as Auth, c as AuthChangeEvent, d as AuthStateChangeCallback, C as ChatCompletion, e as ChatCompletionChoice, f as ChatCompletionChunk, g as ChatCompletionUsage, h as ConnectionState, D as Database, E as Emails, i as EmbeddingsResult, j as EventCallback, F as FunctionInvokeOptions, k as Functions, H as HttpClient, I as ImageGenerationResult, L as Logger, l as Realtime, S as Storage, m as StorageBucket, n as StorageResponse } from './client-
|
|
3
|
-
import { R as ResultAdminConfig, a as ResultConfig } from './types-
|
|
4
|
-
export { A as Analytics, b as AnalyticsOptions, c as ApiError, d as AuthErrorResponse, e as AuthSession, C as ChatCompletionRequest, f as ChatMessageSchema, g as CreateSessionRequest, h as CreateUserRequest, D as DeleteObjectResult, i as DeleteObjectsResponse, E as ERROR_CODES, j as EmbeddingsRequest, k as ErrorCode, I as ImageGenerationRequest, O as OAUTH_PROVIDERS, l as OAuthProvidersSchema, P as PresenceMember, m as ProfileSchema, n as RealtimeErrorPayload, o as ResultError, p as ResultErrorCode, S as SendEmailOptions, q as SendEmailResponse, r as SocketMessage, s as StartThreadOptions, t as StartedThread, u as StorageFileSchema, v as SubscribeResponse, w as Support, x as SupportMessage, y as SupportOptions, z as SupportThread, T as Tool, B as ToolCall, F as ToolChoice, U as UserSchema } from './types-
|
|
1
|
+
import { R as ResultClient } from './client-N6MW9IE1.cjs';
|
|
2
|
+
export { A as AI, a as AccessTokenChangeEvent, b as Auth, c as AuthChangeEvent, d as AuthStateChangeCallback, C as ChatCompletion, e as ChatCompletionChoice, f as ChatCompletionChunk, g as ChatCompletionUsage, h as ConnectionState, D as Database, E as Emails, i as EmbeddingsResult, j as EventCallback, F as FunctionInvokeOptions, k as Functions, H as HttpClient, I as ImageGenerationResult, L as Logger, l as Realtime, S as Storage, m as StorageBucket, n as StorageResponse } from './client-N6MW9IE1.cjs';
|
|
3
|
+
import { R as ResultAdminConfig, a as ResultConfig } from './types-BTdjI7Yj.cjs';
|
|
4
|
+
export { A as Analytics, b as AnalyticsOptions, c as ApiError, d as AuthErrorResponse, e as AuthSession, C as ChatCompletionRequest, f as ChatMessageSchema, g as CreateSessionRequest, h as CreateUserRequest, D as DeleteObjectResult, i as DeleteObjectsResponse, E as ERROR_CODES, j as EmbeddingsRequest, k as ErrorCode, I as ImageGenerationRequest, O as OAUTH_PROVIDERS, l as OAuthProvidersSchema, P as PresenceMember, m as ProfileSchema, n as RealtimeErrorPayload, o as ResultError, p as ResultErrorCode, S as SendEmailOptions, q as SendEmailResponse, r as SocketMessage, s as StartThreadOptions, t as StartedThread, u as StorageFileSchema, v as SubscribeResponse, w as Support, x as SupportMessage, y as SupportOptions, z as SupportThread, T as Tool, B as ToolCall, F as ToolChoice, U as UserSchema } from './types-BTdjI7Yj.cjs';
|
|
5
5
|
import '@supabase/postgrest-js';
|
|
6
6
|
|
|
7
7
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { R as ResultClient } from './client-
|
|
2
|
-
export { A as AI, a as AccessTokenChangeEvent, b as Auth, c as AuthChangeEvent, d as AuthStateChangeCallback, C as ChatCompletion, e as ChatCompletionChoice, f as ChatCompletionChunk, g as ChatCompletionUsage, h as ConnectionState, D as Database, E as Emails, i as EmbeddingsResult, j as EventCallback, F as FunctionInvokeOptions, k as Functions, H as HttpClient, I as ImageGenerationResult, L as Logger, l as Realtime, S as Storage, m as StorageBucket, n as StorageResponse } from './client-
|
|
3
|
-
import { R as ResultAdminConfig, a as ResultConfig } from './types-
|
|
4
|
-
export { A as Analytics, b as AnalyticsOptions, c as ApiError, d as AuthErrorResponse, e as AuthSession, C as ChatCompletionRequest, f as ChatMessageSchema, g as CreateSessionRequest, h as CreateUserRequest, D as DeleteObjectResult, i as DeleteObjectsResponse, E as ERROR_CODES, j as EmbeddingsRequest, k as ErrorCode, I as ImageGenerationRequest, O as OAUTH_PROVIDERS, l as OAuthProvidersSchema, P as PresenceMember, m as ProfileSchema, n as RealtimeErrorPayload, o as ResultError, p as ResultErrorCode, S as SendEmailOptions, q as SendEmailResponse, r as SocketMessage, s as StartThreadOptions, t as StartedThread, u as StorageFileSchema, v as SubscribeResponse, w as Support, x as SupportMessage, y as SupportOptions, z as SupportThread, T as Tool, B as ToolCall, F as ToolChoice, U as UserSchema } from './types-
|
|
1
|
+
import { R as ResultClient } from './client-D5IGLPW4.js';
|
|
2
|
+
export { A as AI, a as AccessTokenChangeEvent, b as Auth, c as AuthChangeEvent, d as AuthStateChangeCallback, C as ChatCompletion, e as ChatCompletionChoice, f as ChatCompletionChunk, g as ChatCompletionUsage, h as ConnectionState, D as Database, E as Emails, i as EmbeddingsResult, j as EventCallback, F as FunctionInvokeOptions, k as Functions, H as HttpClient, I as ImageGenerationResult, L as Logger, l as Realtime, S as Storage, m as StorageBucket, n as StorageResponse } from './client-D5IGLPW4.js';
|
|
3
|
+
import { R as ResultAdminConfig, a as ResultConfig } from './types-BTdjI7Yj.js';
|
|
4
|
+
export { A as Analytics, b as AnalyticsOptions, c as ApiError, d as AuthErrorResponse, e as AuthSession, C as ChatCompletionRequest, f as ChatMessageSchema, g as CreateSessionRequest, h as CreateUserRequest, D as DeleteObjectResult, i as DeleteObjectsResponse, E as ERROR_CODES, j as EmbeddingsRequest, k as ErrorCode, I as ImageGenerationRequest, O as OAUTH_PROVIDERS, l as OAuthProvidersSchema, P as PresenceMember, m as ProfileSchema, n as RealtimeErrorPayload, o as ResultError, p as ResultErrorCode, S as SendEmailOptions, q as SendEmailResponse, r as SocketMessage, s as StartThreadOptions, t as StartedThread, u as StorageFileSchema, v as SubscribeResponse, w as Support, x as SupportMessage, y as SupportOptions, z as SupportThread, T as Tool, B as ToolCall, F as ToolChoice, U as UserSchema } from './types-BTdjI7Yj.js';
|
|
5
5
|
import '@supabase/postgrest-js';
|
|
6
6
|
|
|
7
7
|
/**
|
package/dist/index.js
CHANGED
|
@@ -448,7 +448,15 @@ var HttpClient = class {
|
|
|
448
448
|
*/
|
|
449
449
|
constructor(config, tokenManager, logger) {
|
|
450
450
|
this.config = config;
|
|
451
|
-
|
|
451
|
+
if (!config.baseUrl) {
|
|
452
|
+
throw new ResultError(
|
|
453
|
+
"createClient needs a baseUrl, but it was undefined at runtime.",
|
|
454
|
+
0,
|
|
455
|
+
"MISSING_BASE_URL",
|
|
456
|
+
"Pass the NEXT_PUBLIC_BACKEND_URL value from .env.local. In browser code, write process.env.NEXT_PUBLIC_BACKEND_URL as a literal expression (never through an imported process module) so the bundler inlines it, and set it as a deployments build variable before deploying."
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
this.baseUrl = config.baseUrl;
|
|
452
460
|
this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
|
|
453
461
|
this.anonKey = config.anonKey;
|
|
454
462
|
this.defaultHeaders = {
|
|
@@ -539,6 +547,7 @@ var HttpClient = class {
|
|
|
539
547
|
}
|
|
540
548
|
let controller;
|
|
541
549
|
let timer;
|
|
550
|
+
let removeCallerAbortListener;
|
|
542
551
|
if (this.timeout > 0 || callerSignal) {
|
|
543
552
|
controller = new AbortController();
|
|
544
553
|
if (this.timeout > 0) {
|
|
@@ -552,16 +561,11 @@ var HttpClient = class {
|
|
|
552
561
|
callerSignal.addEventListener("abort", onCallerAbort, {
|
|
553
562
|
once: true
|
|
554
563
|
});
|
|
555
|
-
|
|
556
|
-
"abort",
|
|
557
|
-
() => {
|
|
558
|
-
callerSignal.removeEventListener("abort", onCallerAbort);
|
|
559
|
-
},
|
|
560
|
-
{ once: true }
|
|
561
|
-
);
|
|
564
|
+
removeCallerAbortListener = () => callerSignal.removeEventListener("abort", onCallerAbort);
|
|
562
565
|
}
|
|
563
566
|
}
|
|
564
567
|
}
|
|
568
|
+
let detachOnExit = true;
|
|
565
569
|
try {
|
|
566
570
|
const response = await this.fetch(url, {
|
|
567
571
|
method,
|
|
@@ -582,14 +586,9 @@ var HttpClient = class {
|
|
|
582
586
|
);
|
|
583
587
|
continue;
|
|
584
588
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
}
|
|
588
|
-
return response;
|
|
589
|
+
detachOnExit = false;
|
|
590
|
+
return { response, releaseCallerSignal: removeCallerAbortListener };
|
|
589
591
|
} catch (err) {
|
|
590
|
-
if (timer !== void 0) {
|
|
591
|
-
clearTimeout(timer);
|
|
592
|
-
}
|
|
593
592
|
if (err?.name === "AbortError") {
|
|
594
593
|
if (controller?.signal.aborted && this.timeout > 0 && !callerSignal?.aborted) {
|
|
595
594
|
throw new ResultError(
|
|
@@ -609,6 +608,13 @@ var HttpClient = class {
|
|
|
609
608
|
0,
|
|
610
609
|
"NETWORK_ERROR"
|
|
611
610
|
);
|
|
611
|
+
} finally {
|
|
612
|
+
if (timer !== void 0) {
|
|
613
|
+
clearTimeout(timer);
|
|
614
|
+
}
|
|
615
|
+
if (detachOnExit) {
|
|
616
|
+
removeCallerAbortListener?.();
|
|
617
|
+
}
|
|
612
618
|
}
|
|
613
619
|
}
|
|
614
620
|
throw lastError || new ResultError(
|
|
@@ -671,7 +677,7 @@ var HttpClient = class {
|
|
|
671
677
|
});
|
|
672
678
|
}
|
|
673
679
|
this.logger.logRequest(method, url, requestHeaders, processedBody);
|
|
674
|
-
const response = await this.fetchWithRetry({
|
|
680
|
+
const { response, releaseCallerSignal } = await this.fetchWithRetry({
|
|
675
681
|
method,
|
|
676
682
|
url,
|
|
677
683
|
headers: requestHeaders,
|
|
@@ -694,6 +700,8 @@ var HttpClient = class {
|
|
|
694
700
|
);
|
|
695
701
|
}
|
|
696
702
|
throw err;
|
|
703
|
+
} finally {
|
|
704
|
+
releaseCallerSignal?.();
|
|
697
705
|
}
|
|
698
706
|
this.logger.logResponse(
|
|
699
707
|
method,
|
|
@@ -795,7 +803,7 @@ var HttpClient = class {
|
|
|
795
803
|
const callerSignal = initSignal ?? request?.signal;
|
|
796
804
|
const maxAttempts = IDEMPOTENT_METHODS.has(method.toUpperCase()) ? this.retryCount : 0;
|
|
797
805
|
this.logger.logRequest(method, url, requestHeaders, body);
|
|
798
|
-
const response = await this.fetchWithRetry({
|
|
806
|
+
const { response } = await this.fetchWithRetry({
|
|
799
807
|
method,
|
|
800
808
|
url,
|
|
801
809
|
headers: requestHeaders,
|
|
@@ -896,6 +904,10 @@ var HttpClient = class {
|
|
|
896
904
|
}
|
|
897
905
|
return headers;
|
|
898
906
|
}
|
|
907
|
+
/** Returns the publishable project key used to identify SDK usage reports. */
|
|
908
|
+
getAnonKey() {
|
|
909
|
+
return this.anonKey;
|
|
910
|
+
}
|
|
899
911
|
async refreshAccessToken() {
|
|
900
912
|
if (this.isRefreshing) {
|
|
901
913
|
return this.refreshPromise;
|
|
@@ -965,6 +977,47 @@ var HttpClient = class {
|
|
|
965
977
|
}
|
|
966
978
|
};
|
|
967
979
|
|
|
980
|
+
// src/modules/ai-usage.ts
|
|
981
|
+
var USAGE_ENDPOINT = "https://beta.result.dev/api/usage/ai";
|
|
982
|
+
async function reportAiUsage(http, requestId, model, kind, tokens) {
|
|
983
|
+
const anonKey = http.getAnonKey();
|
|
984
|
+
if (!anonKey || !Number.isSafeInteger(tokens) || tokens <= 0) {
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
const controller = new AbortController();
|
|
988
|
+
const timeout = setTimeout(() => controller.abort(), 2e3);
|
|
989
|
+
try {
|
|
990
|
+
const request = {
|
|
991
|
+
method: "POST",
|
|
992
|
+
headers: { "content-type": "application/json" },
|
|
993
|
+
body: JSON.stringify({
|
|
994
|
+
requestId,
|
|
995
|
+
backendUrl: http.baseUrl,
|
|
996
|
+
anonKey,
|
|
997
|
+
model,
|
|
998
|
+
kind,
|
|
999
|
+
tokens
|
|
1000
|
+
}),
|
|
1001
|
+
keepalive: true,
|
|
1002
|
+
signal: controller.signal
|
|
1003
|
+
};
|
|
1004
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
1005
|
+
try {
|
|
1006
|
+
const response = await http.fetch(USAGE_ENDPOINT, request);
|
|
1007
|
+
if (response.status < 500) return;
|
|
1008
|
+
} catch {
|
|
1009
|
+
if (controller.signal.aborted) return;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
} catch {
|
|
1013
|
+
} finally {
|
|
1014
|
+
clearTimeout(timeout);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
function aiUsageRequestId() {
|
|
1018
|
+
return globalThis.crypto?.randomUUID?.() ?? null;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
968
1021
|
// src/modules/ai.ts
|
|
969
1022
|
var SUPPORTED_AUDIO_FORMATS = [
|
|
970
1023
|
"wav",
|
|
@@ -1052,6 +1105,7 @@ var ChatCompletions = class {
|
|
|
1052
1105
|
}
|
|
1053
1106
|
http;
|
|
1054
1107
|
async create(params) {
|
|
1108
|
+
const usageRequestId = aiUsageRequestId();
|
|
1055
1109
|
const contentSummary = summarizeContent(params.messages ?? []);
|
|
1056
1110
|
assertSupportedContent(params.model, contentSummary);
|
|
1057
1111
|
const backendParams = {
|
|
@@ -1096,7 +1150,7 @@ var ChatCompletions = class {
|
|
|
1096
1150
|
contentSummary
|
|
1097
1151
|
);
|
|
1098
1152
|
}
|
|
1099
|
-
return this.parseSSEStream(response2, params.model);
|
|
1153
|
+
return this.parseSSEStream(response2, params.model, usageRequestId);
|
|
1100
1154
|
}
|
|
1101
1155
|
let response;
|
|
1102
1156
|
try {
|
|
@@ -1105,6 +1159,16 @@ var ChatCompletions = class {
|
|
|
1105
1159
|
throw enrichUpstreamError(error, contentSummary);
|
|
1106
1160
|
}
|
|
1107
1161
|
const content = response.text || "";
|
|
1162
|
+
const totalTokens = response.metadata?.usage?.totalTokens || 0;
|
|
1163
|
+
if (usageRequestId) {
|
|
1164
|
+
await reportAiUsage(
|
|
1165
|
+
this.http,
|
|
1166
|
+
usageRequestId,
|
|
1167
|
+
params.model,
|
|
1168
|
+
"chat",
|
|
1169
|
+
totalTokens
|
|
1170
|
+
);
|
|
1171
|
+
}
|
|
1108
1172
|
return {
|
|
1109
1173
|
id: `chatcmpl-${Date.now()}`,
|
|
1110
1174
|
object: "chat.completion",
|
|
@@ -1131,14 +1195,14 @@ var ChatCompletions = class {
|
|
|
1131
1195
|
usage: {
|
|
1132
1196
|
prompt_tokens: response.metadata?.usage?.promptTokens || 0,
|
|
1133
1197
|
completion_tokens: response.metadata?.usage?.completionTokens || 0,
|
|
1134
|
-
total_tokens:
|
|
1198
|
+
total_tokens: totalTokens
|
|
1135
1199
|
}
|
|
1136
1200
|
};
|
|
1137
1201
|
}
|
|
1138
1202
|
/**
|
|
1139
1203
|
* Parse SSE stream into async iterable of OpenAI-like chunks
|
|
1140
1204
|
*/
|
|
1141
|
-
async *parseSSEStream(response, model) {
|
|
1205
|
+
async *parseSSEStream(response, model, usageRequestId) {
|
|
1142
1206
|
const reader = response.body?.getReader();
|
|
1143
1207
|
if (!reader) {
|
|
1144
1208
|
throw new ResultError(
|
|
@@ -1216,6 +1280,15 @@ var ChatCompletions = class {
|
|
|
1216
1280
|
};
|
|
1217
1281
|
}
|
|
1218
1282
|
if (data.tokenUsage) {
|
|
1283
|
+
if (usageRequestId) {
|
|
1284
|
+
await reportAiUsage(
|
|
1285
|
+
this.http,
|
|
1286
|
+
usageRequestId,
|
|
1287
|
+
model,
|
|
1288
|
+
"chat",
|
|
1289
|
+
data.tokenUsage.totalTokens || 0
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1219
1292
|
yield {
|
|
1220
1293
|
id: `chatcmpl-${Date.now()}`,
|
|
1221
1294
|
object: "chat.completion.chunk",
|
|
@@ -1287,17 +1360,28 @@ var Embeddings = class {
|
|
|
1287
1360
|
* ```
|
|
1288
1361
|
*/
|
|
1289
1362
|
async create(params) {
|
|
1363
|
+
const usageRequestId = aiUsageRequestId();
|
|
1290
1364
|
const response = await this.http.post(
|
|
1291
1365
|
"/api/ai/embeddings",
|
|
1292
1366
|
params
|
|
1293
1367
|
);
|
|
1368
|
+
const totalTokens = response.metadata?.usage?.totalTokens || 0;
|
|
1369
|
+
if (usageRequestId) {
|
|
1370
|
+
await reportAiUsage(
|
|
1371
|
+
this.http,
|
|
1372
|
+
usageRequestId,
|
|
1373
|
+
params.model,
|
|
1374
|
+
"embeddings",
|
|
1375
|
+
totalTokens
|
|
1376
|
+
);
|
|
1377
|
+
}
|
|
1294
1378
|
return {
|
|
1295
1379
|
object: response.object,
|
|
1296
1380
|
data: response.data,
|
|
1297
1381
|
model: response.metadata?.model,
|
|
1298
1382
|
usage: response.metadata?.usage ? {
|
|
1299
1383
|
prompt_tokens: response.metadata.usage.promptTokens || 0,
|
|
1300
|
-
total_tokens:
|
|
1384
|
+
total_tokens: totalTokens
|
|
1301
1385
|
} : {
|
|
1302
1386
|
prompt_tokens: 0,
|
|
1303
1387
|
total_tokens: 0
|
|
@@ -1335,6 +1419,7 @@ var Images = class {
|
|
|
1335
1419
|
* ```
|
|
1336
1420
|
*/
|
|
1337
1421
|
async generate(params) {
|
|
1422
|
+
const usageRequestId = aiUsageRequestId();
|
|
1338
1423
|
const response = await this.http.post(
|
|
1339
1424
|
"/api/ai/image/generation",
|
|
1340
1425
|
params
|
|
@@ -1348,6 +1433,16 @@ var Images = class {
|
|
|
1348
1433
|
} else if (response.text) {
|
|
1349
1434
|
data = [{ content: response.text }];
|
|
1350
1435
|
}
|
|
1436
|
+
const totalTokens = response.metadata?.usage?.totalTokens || 0;
|
|
1437
|
+
if (usageRequestId) {
|
|
1438
|
+
await reportAiUsage(
|
|
1439
|
+
this.http,
|
|
1440
|
+
usageRequestId,
|
|
1441
|
+
params.model,
|
|
1442
|
+
"image",
|
|
1443
|
+
totalTokens
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1351
1446
|
return {
|
|
1352
1447
|
created: Math.floor(Date.now() / 1e3),
|
|
1353
1448
|
data,
|