@resultdev/sdk 0.2.0 → 0.3.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/CHANGELOG.md +32 -0
- package/dist/{client-Z0zUHGE3.d.ts → client-CJv_awPt.d.cts} +60 -30
- package/dist/{client-DeE086La.d.cts → client-DrsZ1qIm.d.ts} +60 -30
- package/dist/index.cjs +161 -19
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +161 -19
- package/dist/{middleware-TGaDOhE9.d.ts → middleware-BJl9JRg3.d.ts} +1 -1
- package/dist/{middleware-BBY_6hyx.d.cts → middleware-C1Z6aMvn.d.cts} +1 -1
- package/dist/ssr/middleware.d.cts +2 -2
- package/dist/ssr/middleware.d.ts +2 -2
- package/dist/ssr.cjs +161 -19
- package/dist/ssr.d.cts +4 -4
- package/dist/ssr.d.ts +4 -4
- package/dist/ssr.js +161 -19
- package/dist/{types-CbsaMttt.d.cts → types-DSVtGaIA.d.cts} +9 -1
- package/dist/{types-CbsaMttt.d.ts → types-DSVtGaIA.d.ts} +9 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @resultdev/sdk
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
Reliability release: every fix here comes from live verification against a
|
|
6
|
+
freshly provisioned backend.
|
|
7
|
+
|
|
8
|
+
- Functions: `invoke()` now goes through the main host's `/functions/{slug}`
|
|
9
|
+
route by default. The legacy subhosting fast-path was retired upstream and
|
|
10
|
+
broke browser calls entirely (its preflight 404s surfaced as
|
|
11
|
+
`TypeError: Failed to fetch`). The main route works from browsers with
|
|
12
|
+
correct CORS. In-process dispatch inside deployments is unchanged, and an
|
|
13
|
+
explicit `functionsUrl` is still honored (now with fallback to the main
|
|
14
|
+
route on network failure, not just 404).
|
|
15
|
+
- Realtime: incoming `meta.channel` had a transport prefix
|
|
16
|
+
(`realtime:chat:1` for a subscription to `chat:1`), so the natural
|
|
17
|
+
`msg.meta.channel === channel` filter silently dropped every message. The
|
|
18
|
+
SDK now strips the prefix before delivery; presence join/leave tracking is
|
|
19
|
+
fixed by the same change.
|
|
20
|
+
- Realtime docs: payload fields arrive spread onto the message (not under a
|
|
21
|
+
`payload` key), and the sender receives its own broadcast; dedupe with
|
|
22
|
+
`meta.messageId`.
|
|
23
|
+
- AI: streaming responses now surface web-search/file citations
|
|
24
|
+
(`chunk.choices[0].delta.annotations`, trailing chunk) and token usage
|
|
25
|
+
(`chunk.usage`). Both were silently dropped before.
|
|
26
|
+
- AI: deterministic bad requests fail fast with specific errors instead of
|
|
27
|
+
an opaque upstream 4xx after a round trip: unsupported audio formats
|
|
28
|
+
(browser MediaRecorder webm/opus included) and audio input on `openai/*`
|
|
29
|
+
models. Upstream provider errors on image/audio requests now name
|
|
30
|
+
`google/gemini-2.5-flash` as the verified multimodal model.
|
|
31
|
+
- Docs: session model documented on `auth` (httpOnly cookie + in-memory
|
|
32
|
+
token; localStorage is empty by design), verified model names in every AI
|
|
33
|
+
example, return shapes clarified across modules.
|
|
34
|
+
|
|
3
35
|
## 0.2.0
|
|
4
36
|
|
|
5
37
|
The SDK is now built fully first-party instead of wrapping a bundled
|
|
@@ -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-DSVtGaIA.cjs';
|
|
2
2
|
import * as _supabase_postgrest_js from '@supabase/postgrest-js';
|
|
3
3
|
import { PostgrestClient } from '@supabase/postgrest-js';
|
|
4
4
|
|
|
@@ -248,9 +248,13 @@ interface ChatCompletionChunk {
|
|
|
248
248
|
delta: {
|
|
249
249
|
content?: string;
|
|
250
250
|
tool_calls?: ToolCall[];
|
|
251
|
+
/** Web-search/file citations; arrives in a trailing chunk. */
|
|
252
|
+
annotations?: Annotation[];
|
|
251
253
|
};
|
|
252
254
|
finish_reason: "tool_calls" | null;
|
|
253
255
|
}[];
|
|
256
|
+
/** Token usage; arrives in a trailing chunk with empty choices. */
|
|
257
|
+
usage?: ChatCompletionUsage;
|
|
254
258
|
}
|
|
255
259
|
interface EmbeddingsResult {
|
|
256
260
|
object: "list";
|
|
@@ -293,14 +297,16 @@ declare class ChatCompletions {
|
|
|
293
297
|
* ```typescript
|
|
294
298
|
* // Non-streaming
|
|
295
299
|
* const completion = await client.ai.chat.completions.create({
|
|
296
|
-
* model: 'gpt-
|
|
300
|
+
* model: 'openai/gpt-4o-mini',
|
|
297
301
|
* messages: [{ role: 'user', content: 'Hello!' }]
|
|
298
302
|
* });
|
|
299
303
|
* console.log(completion.choices[0].message.content);
|
|
300
304
|
*
|
|
301
|
-
* // With images
|
|
305
|
+
* // With images. google/gemini-2.5-flash is the verified multimodal
|
|
306
|
+
* // model (openai/gpt-4o and gpt-4o-mini also accept images, but audio
|
|
307
|
+
* // requires gemini). URLs and base64 data URIs both work.
|
|
302
308
|
* const response = await client.ai.chat.completions.create({
|
|
303
|
-
* model: '
|
|
309
|
+
* model: 'google/gemini-2.5-flash',
|
|
304
310
|
* messages: [{
|
|
305
311
|
* role: 'user',
|
|
306
312
|
* content: [
|
|
@@ -310,37 +316,32 @@ declare class ChatCompletions {
|
|
|
310
316
|
* }]
|
|
311
317
|
* });
|
|
312
318
|
*
|
|
313
|
-
* // With
|
|
314
|
-
*
|
|
315
|
-
*
|
|
319
|
+
* // With audio. Base64 data in wav/mp3/aiff/aac/ogg/flac/m4a only -
|
|
320
|
+
* // browser MediaRecorder's webm/opus is rejected; record PCM via the
|
|
321
|
+
* // Web Audio API and encode a 16 kHz mono WAV instead.
|
|
322
|
+
* const audioResponse = await client.ai.chat.completions.create({
|
|
323
|
+
* model: 'google/gemini-2.5-flash',
|
|
316
324
|
* messages: [{
|
|
317
325
|
* role: 'user',
|
|
318
326
|
* content: [
|
|
319
|
-
* { type: 'text', text: '
|
|
320
|
-
* { type: '
|
|
327
|
+
* { type: 'text', text: 'Transcribe this recording' },
|
|
328
|
+
* { type: 'input_audio', input_audio: { data: base64Wav, format: 'wav' } }
|
|
321
329
|
* ]
|
|
322
|
-
* }]
|
|
323
|
-
* fileParser: { enabled: true, pdf: { engine: 'mistral-ocr' } }
|
|
330
|
+
* }]
|
|
324
331
|
* });
|
|
325
332
|
*
|
|
326
|
-
* // With web search
|
|
333
|
+
* // With web search. Non-streaming: citations arrive on
|
|
334
|
+
* // response.choices[0].message.annotations. Streaming: they arrive in a
|
|
335
|
+
* // trailing chunk as chunk.choices[0].delta.annotations.
|
|
327
336
|
* const searchResponse = await client.ai.chat.completions.create({
|
|
328
|
-
* model: 'openai/gpt-
|
|
337
|
+
* model: 'openai/gpt-4o-mini',
|
|
329
338
|
* messages: [{ role: 'user', content: 'What are the latest news about AI?' }],
|
|
330
339
|
* webSearch: { enabled: true, maxResults: 5 }
|
|
331
340
|
* });
|
|
332
|
-
* // Access citations from response.choices[0].message.annotations
|
|
333
|
-
*
|
|
334
|
-
* // With thinking/reasoning mode (Anthropic models)
|
|
335
|
-
* const thinkingResponse = await client.ai.chat.completions.create({
|
|
336
|
-
* model: 'anthropic/claude-3.5-sonnet',
|
|
337
|
-
* messages: [{ role: 'user', content: 'Solve this complex math problem...' }],
|
|
338
|
-
* thinking: true
|
|
339
|
-
* });
|
|
340
341
|
*
|
|
341
342
|
* // Streaming - returns async iterable
|
|
342
343
|
* const stream = await client.ai.chat.completions.create({
|
|
343
|
-
* model: 'gpt-
|
|
344
|
+
* model: 'openai/gpt-4o-mini',
|
|
344
345
|
* messages: [{ role: 'user', content: 'Tell me a story' }],
|
|
345
346
|
* stream: true
|
|
346
347
|
* });
|
|
@@ -452,6 +453,16 @@ type OAuthSignInOptions = {
|
|
|
452
453
|
type OAuthSignInLegacyOptions = OAuthSignInOptions & {
|
|
453
454
|
provider: OAuthProvidersSchema | string;
|
|
454
455
|
};
|
|
456
|
+
/**
|
|
457
|
+
* Authentication client.
|
|
458
|
+
*
|
|
459
|
+
* Session model: the refresh token lives in an httpOnly cookie set by the
|
|
460
|
+
* backend (plus a CSRF cookie); the access token is held in memory and
|
|
461
|
+
* refreshed from that cookie. Nothing auth-related is written to
|
|
462
|
+
* localStorage, so an empty localStorage does NOT mean the user is signed
|
|
463
|
+
* out. Check state with getCurrentUser() or onAuthStateChange(), never by
|
|
464
|
+
* reading browser storage.
|
|
465
|
+
*/
|
|
455
466
|
declare class Auth {
|
|
456
467
|
private http;
|
|
457
468
|
private tokenManager;
|
|
@@ -748,10 +759,10 @@ declare class Functions {
|
|
|
748
759
|
private functionsUrl;
|
|
749
760
|
constructor(http: HttpClient, functionsUrl?: string);
|
|
750
761
|
/**
|
|
751
|
-
* Derive the subhosting URL from the base URL
|
|
752
|
-
* Rewrites the backend base URL to its functions subhosting URL
|
|
762
|
+
* Derive the legacy subhosting URL from the base URL
|
|
753
763
|
* ({appKey}.{region}.<domain> -> {appKey}.functions.<domain>).
|
|
754
|
-
* Only
|
|
764
|
+
* Only used to recognize when a configured functionsUrl still points at
|
|
765
|
+
* the local deployment, so in-process dispatch can short-circuit it.
|
|
755
766
|
*/
|
|
756
767
|
private static deriveSubhostingUrl;
|
|
757
768
|
/**
|
|
@@ -763,11 +774,13 @@ declare class Functions {
|
|
|
763
774
|
* Invoke an Edge Function.
|
|
764
775
|
*
|
|
765
776
|
* Dispatch order:
|
|
766
|
-
* 1. If the platform's in-process dispatch hook is present
|
|
767
|
-
*
|
|
768
|
-
*
|
|
769
|
-
* 2.
|
|
770
|
-
*
|
|
777
|
+
* 1. If the platform's in-process dispatch hook is present and no foreign
|
|
778
|
+
* functionsUrl is configured, call it directly (function-to-function
|
|
779
|
+
* calls inside the same deployment).
|
|
780
|
+
* 2. If a custom functionsUrl is configured, try it; fall back to the
|
|
781
|
+
* proxy path on 404 or network failure.
|
|
782
|
+
* 3. Otherwise, invoke through the main host's /functions/{slug} proxy.
|
|
783
|
+
* This route works from browsers too (correct CORS).
|
|
771
784
|
*
|
|
772
785
|
* @param slug The function slug to invoke
|
|
773
786
|
* @param options Request options
|
|
@@ -811,7 +824,24 @@ declare class Realtime {
|
|
|
811
824
|
get socketId(): string | undefined;
|
|
812
825
|
subscribe(channel: string): Promise<SubscribeResponse>;
|
|
813
826
|
unsubscribe(channel: string): void;
|
|
827
|
+
/**
|
|
828
|
+
* Publish an event to a channel.
|
|
829
|
+
*
|
|
830
|
+
* Delivery notes (verified against a live backend):
|
|
831
|
+
* - Payload fields arrive spread onto the received message itself, next to
|
|
832
|
+
* `meta` - not nested under a `payload` key. Publishing `{ text: "hi" }`
|
|
833
|
+
* means receivers read `msg.text`.
|
|
834
|
+
* - The sender receives its own message too. Deduplicate with
|
|
835
|
+
* `msg.meta.messageId` (or `msg.meta.senderId`) if you also update local
|
|
836
|
+
* state optimistically.
|
|
837
|
+
*/
|
|
814
838
|
publish<T = unknown>(channel: string, event: string, payload: T): Promise<void>;
|
|
839
|
+
/**
|
|
840
|
+
* Listen for an event by name, across all subscribed channels.
|
|
841
|
+
* Filter by channel inside the callback: `msg.meta.channel` always matches
|
|
842
|
+
* the exact name passed to subscribe() (the SDK strips the server's
|
|
843
|
+
* transport prefix before delivery).
|
|
844
|
+
*/
|
|
815
845
|
on<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
|
|
816
846
|
off<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
|
|
817
847
|
once<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
|
|
@@ -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-DSVtGaIA.js';
|
|
2
2
|
import * as _supabase_postgrest_js from '@supabase/postgrest-js';
|
|
3
3
|
import { PostgrestClient } from '@supabase/postgrest-js';
|
|
4
4
|
|
|
@@ -248,9 +248,13 @@ interface ChatCompletionChunk {
|
|
|
248
248
|
delta: {
|
|
249
249
|
content?: string;
|
|
250
250
|
tool_calls?: ToolCall[];
|
|
251
|
+
/** Web-search/file citations; arrives in a trailing chunk. */
|
|
252
|
+
annotations?: Annotation[];
|
|
251
253
|
};
|
|
252
254
|
finish_reason: "tool_calls" | null;
|
|
253
255
|
}[];
|
|
256
|
+
/** Token usage; arrives in a trailing chunk with empty choices. */
|
|
257
|
+
usage?: ChatCompletionUsage;
|
|
254
258
|
}
|
|
255
259
|
interface EmbeddingsResult {
|
|
256
260
|
object: "list";
|
|
@@ -293,14 +297,16 @@ declare class ChatCompletions {
|
|
|
293
297
|
* ```typescript
|
|
294
298
|
* // Non-streaming
|
|
295
299
|
* const completion = await client.ai.chat.completions.create({
|
|
296
|
-
* model: 'gpt-
|
|
300
|
+
* model: 'openai/gpt-4o-mini',
|
|
297
301
|
* messages: [{ role: 'user', content: 'Hello!' }]
|
|
298
302
|
* });
|
|
299
303
|
* console.log(completion.choices[0].message.content);
|
|
300
304
|
*
|
|
301
|
-
* // With images
|
|
305
|
+
* // With images. google/gemini-2.5-flash is the verified multimodal
|
|
306
|
+
* // model (openai/gpt-4o and gpt-4o-mini also accept images, but audio
|
|
307
|
+
* // requires gemini). URLs and base64 data URIs both work.
|
|
302
308
|
* const response = await client.ai.chat.completions.create({
|
|
303
|
-
* model: '
|
|
309
|
+
* model: 'google/gemini-2.5-flash',
|
|
304
310
|
* messages: [{
|
|
305
311
|
* role: 'user',
|
|
306
312
|
* content: [
|
|
@@ -310,37 +316,32 @@ declare class ChatCompletions {
|
|
|
310
316
|
* }]
|
|
311
317
|
* });
|
|
312
318
|
*
|
|
313
|
-
* // With
|
|
314
|
-
*
|
|
315
|
-
*
|
|
319
|
+
* // With audio. Base64 data in wav/mp3/aiff/aac/ogg/flac/m4a only -
|
|
320
|
+
* // browser MediaRecorder's webm/opus is rejected; record PCM via the
|
|
321
|
+
* // Web Audio API and encode a 16 kHz mono WAV instead.
|
|
322
|
+
* const audioResponse = await client.ai.chat.completions.create({
|
|
323
|
+
* model: 'google/gemini-2.5-flash',
|
|
316
324
|
* messages: [{
|
|
317
325
|
* role: 'user',
|
|
318
326
|
* content: [
|
|
319
|
-
* { type: 'text', text: '
|
|
320
|
-
* { type: '
|
|
327
|
+
* { type: 'text', text: 'Transcribe this recording' },
|
|
328
|
+
* { type: 'input_audio', input_audio: { data: base64Wav, format: 'wav' } }
|
|
321
329
|
* ]
|
|
322
|
-
* }]
|
|
323
|
-
* fileParser: { enabled: true, pdf: { engine: 'mistral-ocr' } }
|
|
330
|
+
* }]
|
|
324
331
|
* });
|
|
325
332
|
*
|
|
326
|
-
* // With web search
|
|
333
|
+
* // With web search. Non-streaming: citations arrive on
|
|
334
|
+
* // response.choices[0].message.annotations. Streaming: they arrive in a
|
|
335
|
+
* // trailing chunk as chunk.choices[0].delta.annotations.
|
|
327
336
|
* const searchResponse = await client.ai.chat.completions.create({
|
|
328
|
-
* model: 'openai/gpt-
|
|
337
|
+
* model: 'openai/gpt-4o-mini',
|
|
329
338
|
* messages: [{ role: 'user', content: 'What are the latest news about AI?' }],
|
|
330
339
|
* webSearch: { enabled: true, maxResults: 5 }
|
|
331
340
|
* });
|
|
332
|
-
* // Access citations from response.choices[0].message.annotations
|
|
333
|
-
*
|
|
334
|
-
* // With thinking/reasoning mode (Anthropic models)
|
|
335
|
-
* const thinkingResponse = await client.ai.chat.completions.create({
|
|
336
|
-
* model: 'anthropic/claude-3.5-sonnet',
|
|
337
|
-
* messages: [{ role: 'user', content: 'Solve this complex math problem...' }],
|
|
338
|
-
* thinking: true
|
|
339
|
-
* });
|
|
340
341
|
*
|
|
341
342
|
* // Streaming - returns async iterable
|
|
342
343
|
* const stream = await client.ai.chat.completions.create({
|
|
343
|
-
* model: 'gpt-
|
|
344
|
+
* model: 'openai/gpt-4o-mini',
|
|
344
345
|
* messages: [{ role: 'user', content: 'Tell me a story' }],
|
|
345
346
|
* stream: true
|
|
346
347
|
* });
|
|
@@ -452,6 +453,16 @@ type OAuthSignInOptions = {
|
|
|
452
453
|
type OAuthSignInLegacyOptions = OAuthSignInOptions & {
|
|
453
454
|
provider: OAuthProvidersSchema | string;
|
|
454
455
|
};
|
|
456
|
+
/**
|
|
457
|
+
* Authentication client.
|
|
458
|
+
*
|
|
459
|
+
* Session model: the refresh token lives in an httpOnly cookie set by the
|
|
460
|
+
* backend (plus a CSRF cookie); the access token is held in memory and
|
|
461
|
+
* refreshed from that cookie. Nothing auth-related is written to
|
|
462
|
+
* localStorage, so an empty localStorage does NOT mean the user is signed
|
|
463
|
+
* out. Check state with getCurrentUser() or onAuthStateChange(), never by
|
|
464
|
+
* reading browser storage.
|
|
465
|
+
*/
|
|
455
466
|
declare class Auth {
|
|
456
467
|
private http;
|
|
457
468
|
private tokenManager;
|
|
@@ -748,10 +759,10 @@ declare class Functions {
|
|
|
748
759
|
private functionsUrl;
|
|
749
760
|
constructor(http: HttpClient, functionsUrl?: string);
|
|
750
761
|
/**
|
|
751
|
-
* Derive the subhosting URL from the base URL
|
|
752
|
-
* Rewrites the backend base URL to its functions subhosting URL
|
|
762
|
+
* Derive the legacy subhosting URL from the base URL
|
|
753
763
|
* ({appKey}.{region}.<domain> -> {appKey}.functions.<domain>).
|
|
754
|
-
* Only
|
|
764
|
+
* Only used to recognize when a configured functionsUrl still points at
|
|
765
|
+
* the local deployment, so in-process dispatch can short-circuit it.
|
|
755
766
|
*/
|
|
756
767
|
private static deriveSubhostingUrl;
|
|
757
768
|
/**
|
|
@@ -763,11 +774,13 @@ declare class Functions {
|
|
|
763
774
|
* Invoke an Edge Function.
|
|
764
775
|
*
|
|
765
776
|
* Dispatch order:
|
|
766
|
-
* 1. If the platform's in-process dispatch hook is present
|
|
767
|
-
*
|
|
768
|
-
*
|
|
769
|
-
* 2.
|
|
770
|
-
*
|
|
777
|
+
* 1. If the platform's in-process dispatch hook is present and no foreign
|
|
778
|
+
* functionsUrl is configured, call it directly (function-to-function
|
|
779
|
+
* calls inside the same deployment).
|
|
780
|
+
* 2. If a custom functionsUrl is configured, try it; fall back to the
|
|
781
|
+
* proxy path on 404 or network failure.
|
|
782
|
+
* 3. Otherwise, invoke through the main host's /functions/{slug} proxy.
|
|
783
|
+
* This route works from browsers too (correct CORS).
|
|
771
784
|
*
|
|
772
785
|
* @param slug The function slug to invoke
|
|
773
786
|
* @param options Request options
|
|
@@ -811,7 +824,24 @@ declare class Realtime {
|
|
|
811
824
|
get socketId(): string | undefined;
|
|
812
825
|
subscribe(channel: string): Promise<SubscribeResponse>;
|
|
813
826
|
unsubscribe(channel: string): void;
|
|
827
|
+
/**
|
|
828
|
+
* Publish an event to a channel.
|
|
829
|
+
*
|
|
830
|
+
* Delivery notes (verified against a live backend):
|
|
831
|
+
* - Payload fields arrive spread onto the received message itself, next to
|
|
832
|
+
* `meta` - not nested under a `payload` key. Publishing `{ text: "hi" }`
|
|
833
|
+
* means receivers read `msg.text`.
|
|
834
|
+
* - The sender receives its own message too. Deduplicate with
|
|
835
|
+
* `msg.meta.messageId` (or `msg.meta.senderId`) if you also update local
|
|
836
|
+
* state optimistically.
|
|
837
|
+
*/
|
|
814
838
|
publish<T = unknown>(channel: string, event: string, payload: T): Promise<void>;
|
|
839
|
+
/**
|
|
840
|
+
* Listen for an event by name, across all subscribed channels.
|
|
841
|
+
* Filter by channel inside the callback: `msg.meta.channel` always matches
|
|
842
|
+
* the exact name passed to subscribe() (the SDK strips the server's
|
|
843
|
+
* transport prefix before delivery).
|
|
844
|
+
*/
|
|
815
845
|
on<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
|
|
816
846
|
off<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
|
|
817
847
|
once<T = SocketMessage>(event: string, callback: EventCallback<T>): void;
|
package/dist/index.cjs
CHANGED
|
@@ -1021,6 +1021,70 @@ var HttpClient = class {
|
|
|
1021
1021
|
};
|
|
1022
1022
|
|
|
1023
1023
|
// src/modules/ai.ts
|
|
1024
|
+
var SUPPORTED_AUDIO_FORMATS = [
|
|
1025
|
+
"wav",
|
|
1026
|
+
"mp3",
|
|
1027
|
+
"aiff",
|
|
1028
|
+
"aac",
|
|
1029
|
+
"ogg",
|
|
1030
|
+
"flac",
|
|
1031
|
+
"m4a"
|
|
1032
|
+
];
|
|
1033
|
+
var MULTIMODAL_MODEL = "google/gemini-2.5-flash";
|
|
1034
|
+
function summarizeContent(messages) {
|
|
1035
|
+
const summary = {
|
|
1036
|
+
hasImage: false,
|
|
1037
|
+
hasAudio: false,
|
|
1038
|
+
badAudioFormats: []
|
|
1039
|
+
};
|
|
1040
|
+
for (const message of messages) {
|
|
1041
|
+
if (message.images?.length) {
|
|
1042
|
+
summary.hasImage = true;
|
|
1043
|
+
}
|
|
1044
|
+
if (!Array.isArray(message.content)) {
|
|
1045
|
+
continue;
|
|
1046
|
+
}
|
|
1047
|
+
for (const part of message.content) {
|
|
1048
|
+
if (part?.type === "image_url") {
|
|
1049
|
+
summary.hasImage = true;
|
|
1050
|
+
} else if (part?.type === "input_audio") {
|
|
1051
|
+
summary.hasAudio = true;
|
|
1052
|
+
const format2 = part.input_audio?.format;
|
|
1053
|
+
if (format2 && !SUPPORTED_AUDIO_FORMATS.includes(format2)) {
|
|
1054
|
+
summary.badAudioFormats.push(format2);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
return summary;
|
|
1060
|
+
}
|
|
1061
|
+
function assertSupportedContent(model, summary) {
|
|
1062
|
+
if (summary.badAudioFormats.length) {
|
|
1063
|
+
throw new ResultError(
|
|
1064
|
+
`Audio format "${summary.badAudioFormats[0]}" is not supported. Supported formats: ${SUPPORTED_AUDIO_FORMATS.join(", ")}. Browser MediaRecorder produces webm/opus, which the gateway rejects - capture PCM with the Web Audio API and encode a 16 kHz mono WAV instead.`,
|
|
1065
|
+
400,
|
|
1066
|
+
"AI_INVALID_INPUT"
|
|
1067
|
+
);
|
|
1068
|
+
}
|
|
1069
|
+
if (summary.hasAudio && model.startsWith("openai/")) {
|
|
1070
|
+
throw new ResultError(
|
|
1071
|
+
`Model "${model}" does not accept audio input on this gateway. Use ${MULTIMODAL_MODEL} (verified for audio).`,
|
|
1072
|
+
400,
|
|
1073
|
+
"AI_INVALID_INPUT"
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
function enrichUpstreamError(error, summary) {
|
|
1078
|
+
if (!(error instanceof ResultError) || error.error !== "AI_UPSTREAM_UNAVAILABLE" || !summary.hasImage && !summary.hasAudio) {
|
|
1079
|
+
return error;
|
|
1080
|
+
}
|
|
1081
|
+
const kind = summary.hasImage && summary.hasAudio ? "image and audio" : summary.hasImage ? "image" : "audio";
|
|
1082
|
+
return new ResultError(
|
|
1083
|
+
`${error.message} This request included ${kind} input; if the error persists, use ${MULTIMODAL_MODEL} (verified for vision and audio).`,
|
|
1084
|
+
error.statusCode,
|
|
1085
|
+
error.error
|
|
1086
|
+
);
|
|
1087
|
+
}
|
|
1024
1088
|
var AI = class {
|
|
1025
1089
|
chat;
|
|
1026
1090
|
images;
|
|
@@ -1043,6 +1107,8 @@ var ChatCompletions = class {
|
|
|
1043
1107
|
}
|
|
1044
1108
|
http;
|
|
1045
1109
|
async create(params) {
|
|
1110
|
+
const contentSummary = summarizeContent(params.messages ?? []);
|
|
1111
|
+
assertSupportedContent(params.model, contentSummary);
|
|
1046
1112
|
const backendParams = {
|
|
1047
1113
|
model: params.model,
|
|
1048
1114
|
messages: params.messages,
|
|
@@ -1071,15 +1137,28 @@ var ChatCompletions = class {
|
|
|
1071
1137
|
}
|
|
1072
1138
|
);
|
|
1073
1139
|
if (!response2.ok) {
|
|
1074
|
-
|
|
1075
|
-
|
|
1140
|
+
let body = null;
|
|
1141
|
+
try {
|
|
1142
|
+
body = await response2.json();
|
|
1143
|
+
} catch {
|
|
1144
|
+
}
|
|
1145
|
+
throw enrichUpstreamError(
|
|
1146
|
+
new ResultError(
|
|
1147
|
+
body?.message || body?.error || "Stream request failed",
|
|
1148
|
+
body?.statusCode ?? response2.status,
|
|
1149
|
+
body?.error || "AI_STREAM_ERROR"
|
|
1150
|
+
),
|
|
1151
|
+
contentSummary
|
|
1152
|
+
);
|
|
1076
1153
|
}
|
|
1077
1154
|
return this.parseSSEStream(response2, params.model);
|
|
1078
1155
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
backendParams
|
|
1082
|
-
)
|
|
1156
|
+
let response;
|
|
1157
|
+
try {
|
|
1158
|
+
response = await this.http.post("/api/ai/chat/completion", backendParams);
|
|
1159
|
+
} catch (error) {
|
|
1160
|
+
throw enrichUpstreamError(error, contentSummary);
|
|
1161
|
+
}
|
|
1083
1162
|
const content = response.text || "";
|
|
1084
1163
|
return {
|
|
1085
1164
|
id: `chatcmpl-${Date.now()}`,
|
|
@@ -1174,6 +1253,37 @@ var ChatCompletions = class {
|
|
|
1174
1253
|
]
|
|
1175
1254
|
};
|
|
1176
1255
|
}
|
|
1256
|
+
if (data.annotations?.length) {
|
|
1257
|
+
yield {
|
|
1258
|
+
id: `chatcmpl-${Date.now()}`,
|
|
1259
|
+
object: "chat.completion.chunk",
|
|
1260
|
+
created: Math.floor(Date.now() / 1e3),
|
|
1261
|
+
model,
|
|
1262
|
+
choices: [
|
|
1263
|
+
{
|
|
1264
|
+
index: 0,
|
|
1265
|
+
delta: {
|
|
1266
|
+
annotations: data.annotations
|
|
1267
|
+
},
|
|
1268
|
+
finish_reason: null
|
|
1269
|
+
}
|
|
1270
|
+
]
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
if (data.tokenUsage) {
|
|
1274
|
+
yield {
|
|
1275
|
+
id: `chatcmpl-${Date.now()}`,
|
|
1276
|
+
object: "chat.completion.chunk",
|
|
1277
|
+
created: Math.floor(Date.now() / 1e3),
|
|
1278
|
+
model,
|
|
1279
|
+
choices: [],
|
|
1280
|
+
usage: {
|
|
1281
|
+
prompt_tokens: data.tokenUsage.promptTokens || 0,
|
|
1282
|
+
completion_tokens: data.tokenUsage.completionTokens || 0,
|
|
1283
|
+
total_tokens: data.tokenUsage.totalTokens || 0
|
|
1284
|
+
}
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1177
1287
|
if (data.done) {
|
|
1178
1288
|
reader.releaseLock();
|
|
1179
1289
|
return;
|
|
@@ -2410,13 +2520,13 @@ var Functions = class _Functions {
|
|
|
2410
2520
|
functionsUrl;
|
|
2411
2521
|
constructor(http, functionsUrl) {
|
|
2412
2522
|
this.http = http;
|
|
2413
|
-
this.functionsUrl = functionsUrl
|
|
2523
|
+
this.functionsUrl = functionsUrl;
|
|
2414
2524
|
}
|
|
2415
2525
|
/**
|
|
2416
|
-
* Derive the subhosting URL from the base URL
|
|
2417
|
-
* Rewrites the backend base URL to its functions subhosting URL
|
|
2526
|
+
* Derive the legacy subhosting URL from the base URL
|
|
2418
2527
|
* ({appKey}.{region}.<domain> -> {appKey}.functions.<domain>).
|
|
2419
|
-
* Only
|
|
2528
|
+
* Only used to recognize when a configured functionsUrl still points at
|
|
2529
|
+
* the local deployment, so in-process dispatch can short-circuit it.
|
|
2420
2530
|
*/
|
|
2421
2531
|
static deriveSubhostingUrl(baseUrl) {
|
|
2422
2532
|
try {
|
|
@@ -2449,11 +2559,13 @@ var Functions = class _Functions {
|
|
|
2449
2559
|
* Invoke an Edge Function.
|
|
2450
2560
|
*
|
|
2451
2561
|
* Dispatch order:
|
|
2452
|
-
* 1. If the platform's in-process dispatch hook is present
|
|
2453
|
-
*
|
|
2454
|
-
*
|
|
2455
|
-
* 2.
|
|
2456
|
-
*
|
|
2562
|
+
* 1. If the platform's in-process dispatch hook is present and no foreign
|
|
2563
|
+
* functionsUrl is configured, call it directly (function-to-function
|
|
2564
|
+
* calls inside the same deployment).
|
|
2565
|
+
* 2. If a custom functionsUrl is configured, try it; fall back to the
|
|
2566
|
+
* proxy path on 404 or network failure.
|
|
2567
|
+
* 3. Otherwise, invoke through the main host's /functions/{slug} proxy.
|
|
2568
|
+
* This route works from browsers too (correct CORS).
|
|
2457
2569
|
*
|
|
2458
2570
|
* @param slug The function slug to invoke
|
|
2459
2571
|
* @param options Request options
|
|
@@ -2462,7 +2574,7 @@ var Functions = class _Functions {
|
|
|
2462
2574
|
const { method = "POST", body, headers = {} } = options;
|
|
2463
2575
|
const dispatch = globalThis.__insforge_dispatch__;
|
|
2464
2576
|
const localFunctionsUrl = _Functions.deriveSubhostingUrl(this.http.baseUrl);
|
|
2465
|
-
if (typeof dispatch === "function" && !!localFunctionsUrl && this.functionsUrl === localFunctionsUrl) {
|
|
2577
|
+
if (typeof dispatch === "function" && (this.functionsUrl === void 0 || !!localFunctionsUrl && this.functionsUrl === localFunctionsUrl)) {
|
|
2466
2578
|
try {
|
|
2467
2579
|
const req = this.buildInProcessRequest(slug, method, body, headers);
|
|
2468
2580
|
const res = await dispatch(req);
|
|
@@ -2497,7 +2609,8 @@ var Functions = class _Functions {
|
|
|
2497
2609
|
if (error instanceof Error && error.name === "AbortError") {
|
|
2498
2610
|
throw error;
|
|
2499
2611
|
}
|
|
2500
|
-
|
|
2612
|
+
const unreachable = error instanceof ResultError && (error.statusCode === 404 || error.statusCode === 0);
|
|
2613
|
+
if (unreachable) {
|
|
2501
2614
|
} else {
|
|
2502
2615
|
return {
|
|
2503
2616
|
data: null,
|
|
@@ -2533,6 +2646,17 @@ var Functions = class _Functions {
|
|
|
2533
2646
|
// src/modules/realtime.ts
|
|
2534
2647
|
var CONNECT_TIMEOUT = 1e4;
|
|
2535
2648
|
var SUBSCRIBE_TIMEOUT = 1e4;
|
|
2649
|
+
var CHANNEL_PREFIX = "realtime:";
|
|
2650
|
+
function normalizeChannelMeta(message) {
|
|
2651
|
+
const channel = message?.meta?.channel;
|
|
2652
|
+
if (typeof channel !== "string" || !channel.startsWith(CHANNEL_PREFIX)) {
|
|
2653
|
+
return message;
|
|
2654
|
+
}
|
|
2655
|
+
return {
|
|
2656
|
+
...message,
|
|
2657
|
+
meta: { ...message.meta, channel: channel.slice(CHANNEL_PREFIX.length) }
|
|
2658
|
+
};
|
|
2659
|
+
}
|
|
2536
2660
|
var Realtime = class {
|
|
2537
2661
|
constructor(baseUrl, tokenManager, anonKey, getValidAccessToken = async () => tokenManager.getAccessToken()) {
|
|
2538
2662
|
this.baseUrl = baseUrl;
|
|
@@ -2654,8 +2778,9 @@ var Realtime = class {
|
|
|
2654
2778
|
if (event === "realtime:error") {
|
|
2655
2779
|
return;
|
|
2656
2780
|
}
|
|
2657
|
-
|
|
2658
|
-
this.
|
|
2781
|
+
const normalized = normalizeChannelMeta(message);
|
|
2782
|
+
this.applyPresenceEvent(event, normalized);
|
|
2783
|
+
this.notifyListeners(event, normalized);
|
|
2659
2784
|
};
|
|
2660
2785
|
this.connectionAttempt = { id: attemptId, socket, cancel: fail };
|
|
2661
2786
|
socket.on("connect", onConnect);
|
|
@@ -2903,6 +3028,17 @@ var Realtime = class {
|
|
|
2903
3028
|
this.socket.emit("realtime:unsubscribe", { channel });
|
|
2904
3029
|
}
|
|
2905
3030
|
}
|
|
3031
|
+
/**
|
|
3032
|
+
* Publish an event to a channel.
|
|
3033
|
+
*
|
|
3034
|
+
* Delivery notes (verified against a live backend):
|
|
3035
|
+
* - Payload fields arrive spread onto the received message itself, next to
|
|
3036
|
+
* `meta` - not nested under a `payload` key. Publishing `{ text: "hi" }`
|
|
3037
|
+
* means receivers read `msg.text`.
|
|
3038
|
+
* - The sender receives its own message too. Deduplicate with
|
|
3039
|
+
* `msg.meta.messageId` (or `msg.meta.senderId`) if you also update local
|
|
3040
|
+
* state optimistically.
|
|
3041
|
+
*/
|
|
2906
3042
|
async publish(channel, event, payload) {
|
|
2907
3043
|
if (!this.socket?.connected) {
|
|
2908
3044
|
throw new Error(
|
|
@@ -2911,6 +3047,12 @@ var Realtime = class {
|
|
|
2911
3047
|
}
|
|
2912
3048
|
this.socket.emit("realtime:publish", { channel, event, payload });
|
|
2913
3049
|
}
|
|
3050
|
+
/**
|
|
3051
|
+
* Listen for an event by name, across all subscribed channels.
|
|
3052
|
+
* Filter by channel inside the callback: `msg.meta.channel` always matches
|
|
3053
|
+
* the exact name passed to subscribe() (the SDK strips the server's
|
|
3054
|
+
* transport prefix before delivery).
|
|
3055
|
+
*/
|
|
2914
3056
|
on(event, callback) {
|
|
2915
3057
|
const listeners = this.eventListeners.get(event) ?? /* @__PURE__ */ new Set();
|
|
2916
3058
|
listeners.add(callback);
|
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-CJv_awPt.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-CJv_awPt.cjs';
|
|
3
|
+
import { R as ResultAdminConfig, a as ResultConfig } from './types-DSVtGaIA.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-DSVtGaIA.cjs';
|
|
5
5
|
import '@supabase/postgrest-js';
|
|
6
6
|
|
|
7
7
|
/**
|