@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/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { R as ResultClient } from './client-Z0zUHGE3.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-Z0zUHGE3.js';
3
- import { R as ResultAdminConfig, a as ResultConfig } from './types-CbsaMttt.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-CbsaMttt.js';
1
+ import { R as ResultClient } from './client-DrsZ1qIm.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-DrsZ1qIm.js';
3
+ import { R as ResultAdminConfig, a as ResultConfig } from './types-DSVtGaIA.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-DSVtGaIA.js';
5
5
  import '@supabase/postgrest-js';
6
6
 
7
7
  /**
package/dist/index.js CHANGED
@@ -966,6 +966,70 @@ var HttpClient = class {
966
966
  };
967
967
 
968
968
  // src/modules/ai.ts
969
+ var SUPPORTED_AUDIO_FORMATS = [
970
+ "wav",
971
+ "mp3",
972
+ "aiff",
973
+ "aac",
974
+ "ogg",
975
+ "flac",
976
+ "m4a"
977
+ ];
978
+ var MULTIMODAL_MODEL = "google/gemini-2.5-flash";
979
+ function summarizeContent(messages) {
980
+ const summary = {
981
+ hasImage: false,
982
+ hasAudio: false,
983
+ badAudioFormats: []
984
+ };
985
+ for (const message of messages) {
986
+ if (message.images?.length) {
987
+ summary.hasImage = true;
988
+ }
989
+ if (!Array.isArray(message.content)) {
990
+ continue;
991
+ }
992
+ for (const part of message.content) {
993
+ if (part?.type === "image_url") {
994
+ summary.hasImage = true;
995
+ } else if (part?.type === "input_audio") {
996
+ summary.hasAudio = true;
997
+ const format2 = part.input_audio?.format;
998
+ if (format2 && !SUPPORTED_AUDIO_FORMATS.includes(format2)) {
999
+ summary.badAudioFormats.push(format2);
1000
+ }
1001
+ }
1002
+ }
1003
+ }
1004
+ return summary;
1005
+ }
1006
+ function assertSupportedContent(model, summary) {
1007
+ if (summary.badAudioFormats.length) {
1008
+ throw new ResultError(
1009
+ `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.`,
1010
+ 400,
1011
+ "AI_INVALID_INPUT"
1012
+ );
1013
+ }
1014
+ if (summary.hasAudio && model.startsWith("openai/")) {
1015
+ throw new ResultError(
1016
+ `Model "${model}" does not accept audio input on this gateway. Use ${MULTIMODAL_MODEL} (verified for audio).`,
1017
+ 400,
1018
+ "AI_INVALID_INPUT"
1019
+ );
1020
+ }
1021
+ }
1022
+ function enrichUpstreamError(error, summary) {
1023
+ if (!(error instanceof ResultError) || error.error !== "AI_UPSTREAM_UNAVAILABLE" || !summary.hasImage && !summary.hasAudio) {
1024
+ return error;
1025
+ }
1026
+ const kind = summary.hasImage && summary.hasAudio ? "image and audio" : summary.hasImage ? "image" : "audio";
1027
+ return new ResultError(
1028
+ `${error.message} This request included ${kind} input; if the error persists, use ${MULTIMODAL_MODEL} (verified for vision and audio).`,
1029
+ error.statusCode,
1030
+ error.error
1031
+ );
1032
+ }
969
1033
  var AI = class {
970
1034
  chat;
971
1035
  images;
@@ -988,6 +1052,8 @@ var ChatCompletions = class {
988
1052
  }
989
1053
  http;
990
1054
  async create(params) {
1055
+ const contentSummary = summarizeContent(params.messages ?? []);
1056
+ assertSupportedContent(params.model, contentSummary);
991
1057
  const backendParams = {
992
1058
  model: params.model,
993
1059
  messages: params.messages,
@@ -1016,15 +1082,28 @@ var ChatCompletions = class {
1016
1082
  }
1017
1083
  );
1018
1084
  if (!response2.ok) {
1019
- const error = await response2.json();
1020
- throw new Error(error.error || "Stream request failed");
1085
+ let body = null;
1086
+ try {
1087
+ body = await response2.json();
1088
+ } catch {
1089
+ }
1090
+ throw enrichUpstreamError(
1091
+ new ResultError(
1092
+ body?.message || body?.error || "Stream request failed",
1093
+ body?.statusCode ?? response2.status,
1094
+ body?.error || "AI_STREAM_ERROR"
1095
+ ),
1096
+ contentSummary
1097
+ );
1021
1098
  }
1022
1099
  return this.parseSSEStream(response2, params.model);
1023
1100
  }
1024
- const response = await this.http.post(
1025
- "/api/ai/chat/completion",
1026
- backendParams
1027
- );
1101
+ let response;
1102
+ try {
1103
+ response = await this.http.post("/api/ai/chat/completion", backendParams);
1104
+ } catch (error) {
1105
+ throw enrichUpstreamError(error, contentSummary);
1106
+ }
1028
1107
  const content = response.text || "";
1029
1108
  return {
1030
1109
  id: `chatcmpl-${Date.now()}`,
@@ -1119,6 +1198,37 @@ var ChatCompletions = class {
1119
1198
  ]
1120
1199
  };
1121
1200
  }
1201
+ if (data.annotations?.length) {
1202
+ yield {
1203
+ id: `chatcmpl-${Date.now()}`,
1204
+ object: "chat.completion.chunk",
1205
+ created: Math.floor(Date.now() / 1e3),
1206
+ model,
1207
+ choices: [
1208
+ {
1209
+ index: 0,
1210
+ delta: {
1211
+ annotations: data.annotations
1212
+ },
1213
+ finish_reason: null
1214
+ }
1215
+ ]
1216
+ };
1217
+ }
1218
+ if (data.tokenUsage) {
1219
+ yield {
1220
+ id: `chatcmpl-${Date.now()}`,
1221
+ object: "chat.completion.chunk",
1222
+ created: Math.floor(Date.now() / 1e3),
1223
+ model,
1224
+ choices: [],
1225
+ usage: {
1226
+ prompt_tokens: data.tokenUsage.promptTokens || 0,
1227
+ completion_tokens: data.tokenUsage.completionTokens || 0,
1228
+ total_tokens: data.tokenUsage.totalTokens || 0
1229
+ }
1230
+ };
1231
+ }
1122
1232
  if (data.done) {
1123
1233
  reader.releaseLock();
1124
1234
  return;
@@ -2355,13 +2465,13 @@ var Functions = class _Functions {
2355
2465
  functionsUrl;
2356
2466
  constructor(http, functionsUrl) {
2357
2467
  this.http = http;
2358
- this.functionsUrl = functionsUrl || _Functions.deriveSubhostingUrl(http.baseUrl);
2468
+ this.functionsUrl = functionsUrl;
2359
2469
  }
2360
2470
  /**
2361
- * Derive the subhosting URL from the base URL.
2362
- * Rewrites the backend base URL to its functions subhosting URL
2471
+ * Derive the legacy subhosting URL from the base URL
2363
2472
  * ({appKey}.{region}.<domain> -> {appKey}.functions.<domain>).
2364
- * Only applies to platform-hosted backends.
2473
+ * Only used to recognize when a configured functionsUrl still points at
2474
+ * the local deployment, so in-process dispatch can short-circuit it.
2365
2475
  */
2366
2476
  static deriveSubhostingUrl(baseUrl) {
2367
2477
  try {
@@ -2394,11 +2504,13 @@ var Functions = class _Functions {
2394
2504
  * Invoke an Edge Function.
2395
2505
  *
2396
2506
  * Dispatch order:
2397
- * 1. If the platform's in-process dispatch hook is present, call it directly.
2398
- * This avoids Deno Subhosting's 508 Loop Detected when one bundled
2399
- * function invokes another inside the same deployment.
2400
- * 2. Otherwise, try the configured subhosting URL.
2401
- * 3. On 404 from subhosting, fall back to the proxy path.
2507
+ * 1. If the platform's in-process dispatch hook is present and no foreign
2508
+ * functionsUrl is configured, call it directly (function-to-function
2509
+ * calls inside the same deployment).
2510
+ * 2. If a custom functionsUrl is configured, try it; fall back to the
2511
+ * proxy path on 404 or network failure.
2512
+ * 3. Otherwise, invoke through the main host's /functions/{slug} proxy.
2513
+ * This route works from browsers too (correct CORS).
2402
2514
  *
2403
2515
  * @param slug The function slug to invoke
2404
2516
  * @param options Request options
@@ -2407,7 +2519,7 @@ var Functions = class _Functions {
2407
2519
  const { method = "POST", body, headers = {} } = options;
2408
2520
  const dispatch = globalThis.__insforge_dispatch__;
2409
2521
  const localFunctionsUrl = _Functions.deriveSubhostingUrl(this.http.baseUrl);
2410
- if (typeof dispatch === "function" && !!localFunctionsUrl && this.functionsUrl === localFunctionsUrl) {
2522
+ if (typeof dispatch === "function" && (this.functionsUrl === void 0 || !!localFunctionsUrl && this.functionsUrl === localFunctionsUrl)) {
2411
2523
  try {
2412
2524
  const req = this.buildInProcessRequest(slug, method, body, headers);
2413
2525
  const res = await dispatch(req);
@@ -2442,7 +2554,8 @@ var Functions = class _Functions {
2442
2554
  if (error instanceof Error && error.name === "AbortError") {
2443
2555
  throw error;
2444
2556
  }
2445
- if (error instanceof ResultError && error.statusCode === 404) {
2557
+ const unreachable = error instanceof ResultError && (error.statusCode === 404 || error.statusCode === 0);
2558
+ if (unreachable) {
2446
2559
  } else {
2447
2560
  return {
2448
2561
  data: null,
@@ -2478,6 +2591,17 @@ var Functions = class _Functions {
2478
2591
  // src/modules/realtime.ts
2479
2592
  var CONNECT_TIMEOUT = 1e4;
2480
2593
  var SUBSCRIBE_TIMEOUT = 1e4;
2594
+ var CHANNEL_PREFIX = "realtime:";
2595
+ function normalizeChannelMeta(message) {
2596
+ const channel = message?.meta?.channel;
2597
+ if (typeof channel !== "string" || !channel.startsWith(CHANNEL_PREFIX)) {
2598
+ return message;
2599
+ }
2600
+ return {
2601
+ ...message,
2602
+ meta: { ...message.meta, channel: channel.slice(CHANNEL_PREFIX.length) }
2603
+ };
2604
+ }
2481
2605
  var Realtime = class {
2482
2606
  constructor(baseUrl, tokenManager, anonKey, getValidAccessToken = async () => tokenManager.getAccessToken()) {
2483
2607
  this.baseUrl = baseUrl;
@@ -2599,8 +2723,9 @@ var Realtime = class {
2599
2723
  if (event === "realtime:error") {
2600
2724
  return;
2601
2725
  }
2602
- this.applyPresenceEvent(event, message);
2603
- this.notifyListeners(event, message);
2726
+ const normalized = normalizeChannelMeta(message);
2727
+ this.applyPresenceEvent(event, normalized);
2728
+ this.notifyListeners(event, normalized);
2604
2729
  };
2605
2730
  this.connectionAttempt = { id: attemptId, socket, cancel: fail };
2606
2731
  socket.on("connect", onConnect);
@@ -2848,6 +2973,17 @@ var Realtime = class {
2848
2973
  this.socket.emit("realtime:unsubscribe", { channel });
2849
2974
  }
2850
2975
  }
2976
+ /**
2977
+ * Publish an event to a channel.
2978
+ *
2979
+ * Delivery notes (verified against a live backend):
2980
+ * - Payload fields arrive spread onto the received message itself, next to
2981
+ * `meta` - not nested under a `payload` key. Publishing `{ text: "hi" }`
2982
+ * means receivers read `msg.text`.
2983
+ * - The sender receives its own message too. Deduplicate with
2984
+ * `msg.meta.messageId` (or `msg.meta.senderId`) if you also update local
2985
+ * state optimistically.
2986
+ */
2851
2987
  async publish(channel, event, payload) {
2852
2988
  if (!this.socket?.connected) {
2853
2989
  throw new Error(
@@ -2856,6 +2992,12 @@ var Realtime = class {
2856
2992
  }
2857
2993
  this.socket.emit("realtime:publish", { channel, event, payload });
2858
2994
  }
2995
+ /**
2996
+ * Listen for an event by name, across all subscribed channels.
2997
+ * Filter by channel inside the callback: `msg.meta.channel` always matches
2998
+ * the exact name passed to subscribe() (the SDK strips the server's
2999
+ * transport prefix before delivery).
3000
+ */
2859
3001
  on(event, callback) {
2860
3002
  const listeners = this.eventListeners.get(event) ?? /* @__PURE__ */ new Set();
2861
3003
  listeners.add(callback);
@@ -1,4 +1,4 @@
1
- import { a as ResultConfig, o as ResultError } from './types-CbsaMttt.js';
1
+ import { a as ResultConfig, o as ResultError } from './types-DSVtGaIA.js';
2
2
 
3
3
  declare const DEFAULT_ACCESS_TOKEN_COOKIE = "result_access_token";
4
4
  declare const DEFAULT_REFRESH_TOKEN_COOKIE = "result_refresh_token";
@@ -1,4 +1,4 @@
1
- import { a as ResultConfig, o as ResultError } from './types-CbsaMttt.cjs';
1
+ import { a as ResultConfig, o as ResultError } from './types-DSVtGaIA.cjs';
2
2
 
3
3
  declare const DEFAULT_ACCESS_TOKEN_COOKIE = "result_access_token";
4
4
  declare const DEFAULT_REFRESH_TOKEN_COOKIE = "result_refresh_token";
@@ -1,2 +1,2 @@
1
- export { b as AuthCookieNames, c as AuthCookieOptions, A as AuthCookieSettings, d as CookieOptions, e as CookieReader, C as CookieStore, a as CookieWriter, D as DEFAULT_ACCESS_TOKEN_COOKIE, f as DEFAULT_REFRESH_TOKEN_COOKIE, U as UpdateSessionOptions, g as UpdateSessionResult, i as clearAuthCookies, j as getAccessTokenCookieName, k as getRefreshTokenCookieName, s as setAuthCookies, u as updateSession } from '../middleware-BBY_6hyx.cjs';
2
- import '../types-CbsaMttt.cjs';
1
+ export { b as AuthCookieNames, c as AuthCookieOptions, A as AuthCookieSettings, d as CookieOptions, e as CookieReader, C as CookieStore, a as CookieWriter, D as DEFAULT_ACCESS_TOKEN_COOKIE, f as DEFAULT_REFRESH_TOKEN_COOKIE, U as UpdateSessionOptions, g as UpdateSessionResult, i as clearAuthCookies, j as getAccessTokenCookieName, k as getRefreshTokenCookieName, s as setAuthCookies, u as updateSession } from '../middleware-C1Z6aMvn.cjs';
2
+ import '../types-DSVtGaIA.cjs';
@@ -1,2 +1,2 @@
1
- export { b as AuthCookieNames, c as AuthCookieOptions, A as AuthCookieSettings, d as CookieOptions, e as CookieReader, C as CookieStore, a as CookieWriter, D as DEFAULT_ACCESS_TOKEN_COOKIE, f as DEFAULT_REFRESH_TOKEN_COOKIE, U as UpdateSessionOptions, g as UpdateSessionResult, i as clearAuthCookies, j as getAccessTokenCookieName, k as getRefreshTokenCookieName, s as setAuthCookies, u as updateSession } from '../middleware-TGaDOhE9.js';
2
- import '../types-CbsaMttt.js';
1
+ export { b as AuthCookieNames, c as AuthCookieOptions, A as AuthCookieSettings, d as CookieOptions, e as CookieReader, C as CookieStore, a as CookieWriter, D as DEFAULT_ACCESS_TOKEN_COOKIE, f as DEFAULT_REFRESH_TOKEN_COOKIE, U as UpdateSessionOptions, g as UpdateSessionResult, i as clearAuthCookies, j as getAccessTokenCookieName, k as getRefreshTokenCookieName, s as setAuthCookies, u as updateSession } from '../middleware-BJl9JRg3.js';
2
+ import '../types-DSVtGaIA.js';
package/dist/ssr.cjs CHANGED
@@ -1208,6 +1208,70 @@ var HttpClient = class {
1208
1208
  };
1209
1209
 
1210
1210
  // src/modules/ai.ts
1211
+ var SUPPORTED_AUDIO_FORMATS = [
1212
+ "wav",
1213
+ "mp3",
1214
+ "aiff",
1215
+ "aac",
1216
+ "ogg",
1217
+ "flac",
1218
+ "m4a"
1219
+ ];
1220
+ var MULTIMODAL_MODEL = "google/gemini-2.5-flash";
1221
+ function summarizeContent(messages) {
1222
+ const summary = {
1223
+ hasImage: false,
1224
+ hasAudio: false,
1225
+ badAudioFormats: []
1226
+ };
1227
+ for (const message of messages) {
1228
+ if (message.images?.length) {
1229
+ summary.hasImage = true;
1230
+ }
1231
+ if (!Array.isArray(message.content)) {
1232
+ continue;
1233
+ }
1234
+ for (const part of message.content) {
1235
+ if (part?.type === "image_url") {
1236
+ summary.hasImage = true;
1237
+ } else if (part?.type === "input_audio") {
1238
+ summary.hasAudio = true;
1239
+ const format2 = part.input_audio?.format;
1240
+ if (format2 && !SUPPORTED_AUDIO_FORMATS.includes(format2)) {
1241
+ summary.badAudioFormats.push(format2);
1242
+ }
1243
+ }
1244
+ }
1245
+ }
1246
+ return summary;
1247
+ }
1248
+ function assertSupportedContent(model, summary) {
1249
+ if (summary.badAudioFormats.length) {
1250
+ throw new ResultError(
1251
+ `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.`,
1252
+ 400,
1253
+ "AI_INVALID_INPUT"
1254
+ );
1255
+ }
1256
+ if (summary.hasAudio && model.startsWith("openai/")) {
1257
+ throw new ResultError(
1258
+ `Model "${model}" does not accept audio input on this gateway. Use ${MULTIMODAL_MODEL} (verified for audio).`,
1259
+ 400,
1260
+ "AI_INVALID_INPUT"
1261
+ );
1262
+ }
1263
+ }
1264
+ function enrichUpstreamError(error, summary) {
1265
+ if (!(error instanceof ResultError) || error.error !== "AI_UPSTREAM_UNAVAILABLE" || !summary.hasImage && !summary.hasAudio) {
1266
+ return error;
1267
+ }
1268
+ const kind = summary.hasImage && summary.hasAudio ? "image and audio" : summary.hasImage ? "image" : "audio";
1269
+ return new ResultError(
1270
+ `${error.message} This request included ${kind} input; if the error persists, use ${MULTIMODAL_MODEL} (verified for vision and audio).`,
1271
+ error.statusCode,
1272
+ error.error
1273
+ );
1274
+ }
1211
1275
  var AI = class {
1212
1276
  chat;
1213
1277
  images;
@@ -1230,6 +1294,8 @@ var ChatCompletions = class {
1230
1294
  }
1231
1295
  http;
1232
1296
  async create(params) {
1297
+ const contentSummary = summarizeContent(params.messages ?? []);
1298
+ assertSupportedContent(params.model, contentSummary);
1233
1299
  const backendParams = {
1234
1300
  model: params.model,
1235
1301
  messages: params.messages,
@@ -1258,15 +1324,28 @@ var ChatCompletions = class {
1258
1324
  }
1259
1325
  );
1260
1326
  if (!response2.ok) {
1261
- const error = await response2.json();
1262
- throw new Error(error.error || "Stream request failed");
1327
+ let body = null;
1328
+ try {
1329
+ body = await response2.json();
1330
+ } catch {
1331
+ }
1332
+ throw enrichUpstreamError(
1333
+ new ResultError(
1334
+ body?.message || body?.error || "Stream request failed",
1335
+ body?.statusCode ?? response2.status,
1336
+ body?.error || "AI_STREAM_ERROR"
1337
+ ),
1338
+ contentSummary
1339
+ );
1263
1340
  }
1264
1341
  return this.parseSSEStream(response2, params.model);
1265
1342
  }
1266
- const response = await this.http.post(
1267
- "/api/ai/chat/completion",
1268
- backendParams
1269
- );
1343
+ let response;
1344
+ try {
1345
+ response = await this.http.post("/api/ai/chat/completion", backendParams);
1346
+ } catch (error) {
1347
+ throw enrichUpstreamError(error, contentSummary);
1348
+ }
1270
1349
  const content = response.text || "";
1271
1350
  return {
1272
1351
  id: `chatcmpl-${Date.now()}`,
@@ -1361,6 +1440,37 @@ var ChatCompletions = class {
1361
1440
  ]
1362
1441
  };
1363
1442
  }
1443
+ if (data.annotations?.length) {
1444
+ yield {
1445
+ id: `chatcmpl-${Date.now()}`,
1446
+ object: "chat.completion.chunk",
1447
+ created: Math.floor(Date.now() / 1e3),
1448
+ model,
1449
+ choices: [
1450
+ {
1451
+ index: 0,
1452
+ delta: {
1453
+ annotations: data.annotations
1454
+ },
1455
+ finish_reason: null
1456
+ }
1457
+ ]
1458
+ };
1459
+ }
1460
+ if (data.tokenUsage) {
1461
+ yield {
1462
+ id: `chatcmpl-${Date.now()}`,
1463
+ object: "chat.completion.chunk",
1464
+ created: Math.floor(Date.now() / 1e3),
1465
+ model,
1466
+ choices: [],
1467
+ usage: {
1468
+ prompt_tokens: data.tokenUsage.promptTokens || 0,
1469
+ completion_tokens: data.tokenUsage.completionTokens || 0,
1470
+ total_tokens: data.tokenUsage.totalTokens || 0
1471
+ }
1472
+ };
1473
+ }
1364
1474
  if (data.done) {
1365
1475
  reader.releaseLock();
1366
1476
  return;
@@ -2597,13 +2707,13 @@ var Functions = class _Functions {
2597
2707
  functionsUrl;
2598
2708
  constructor(http, functionsUrl) {
2599
2709
  this.http = http;
2600
- this.functionsUrl = functionsUrl || _Functions.deriveSubhostingUrl(http.baseUrl);
2710
+ this.functionsUrl = functionsUrl;
2601
2711
  }
2602
2712
  /**
2603
- * Derive the subhosting URL from the base URL.
2604
- * Rewrites the backend base URL to its functions subhosting URL
2713
+ * Derive the legacy subhosting URL from the base URL
2605
2714
  * ({appKey}.{region}.<domain> -> {appKey}.functions.<domain>).
2606
- * Only applies to platform-hosted backends.
2715
+ * Only used to recognize when a configured functionsUrl still points at
2716
+ * the local deployment, so in-process dispatch can short-circuit it.
2607
2717
  */
2608
2718
  static deriveSubhostingUrl(baseUrl) {
2609
2719
  try {
@@ -2636,11 +2746,13 @@ var Functions = class _Functions {
2636
2746
  * Invoke an Edge Function.
2637
2747
  *
2638
2748
  * Dispatch order:
2639
- * 1. If the platform's in-process dispatch hook is present, call it directly.
2640
- * This avoids Deno Subhosting's 508 Loop Detected when one bundled
2641
- * function invokes another inside the same deployment.
2642
- * 2. Otherwise, try the configured subhosting URL.
2643
- * 3. On 404 from subhosting, fall back to the proxy path.
2749
+ * 1. If the platform's in-process dispatch hook is present and no foreign
2750
+ * functionsUrl is configured, call it directly (function-to-function
2751
+ * calls inside the same deployment).
2752
+ * 2. If a custom functionsUrl is configured, try it; fall back to the
2753
+ * proxy path on 404 or network failure.
2754
+ * 3. Otherwise, invoke through the main host's /functions/{slug} proxy.
2755
+ * This route works from browsers too (correct CORS).
2644
2756
  *
2645
2757
  * @param slug The function slug to invoke
2646
2758
  * @param options Request options
@@ -2649,7 +2761,7 @@ var Functions = class _Functions {
2649
2761
  const { method = "POST", body, headers = {} } = options;
2650
2762
  const dispatch = globalThis.__insforge_dispatch__;
2651
2763
  const localFunctionsUrl = _Functions.deriveSubhostingUrl(this.http.baseUrl);
2652
- if (typeof dispatch === "function" && !!localFunctionsUrl && this.functionsUrl === localFunctionsUrl) {
2764
+ if (typeof dispatch === "function" && (this.functionsUrl === void 0 || !!localFunctionsUrl && this.functionsUrl === localFunctionsUrl)) {
2653
2765
  try {
2654
2766
  const req = this.buildInProcessRequest(slug, method, body, headers);
2655
2767
  const res = await dispatch(req);
@@ -2684,7 +2796,8 @@ var Functions = class _Functions {
2684
2796
  if (error instanceof Error && error.name === "AbortError") {
2685
2797
  throw error;
2686
2798
  }
2687
- if (error instanceof ResultError && error.statusCode === 404) {
2799
+ const unreachable = error instanceof ResultError && (error.statusCode === 404 || error.statusCode === 0);
2800
+ if (unreachable) {
2688
2801
  } else {
2689
2802
  return {
2690
2803
  data: null,
@@ -2720,6 +2833,17 @@ var Functions = class _Functions {
2720
2833
  // src/modules/realtime.ts
2721
2834
  var CONNECT_TIMEOUT = 1e4;
2722
2835
  var SUBSCRIBE_TIMEOUT = 1e4;
2836
+ var CHANNEL_PREFIX = "realtime:";
2837
+ function normalizeChannelMeta(message) {
2838
+ const channel = message?.meta?.channel;
2839
+ if (typeof channel !== "string" || !channel.startsWith(CHANNEL_PREFIX)) {
2840
+ return message;
2841
+ }
2842
+ return {
2843
+ ...message,
2844
+ meta: { ...message.meta, channel: channel.slice(CHANNEL_PREFIX.length) }
2845
+ };
2846
+ }
2723
2847
  var Realtime = class {
2724
2848
  constructor(baseUrl, tokenManager, anonKey, getValidAccessToken = async () => tokenManager.getAccessToken()) {
2725
2849
  this.baseUrl = baseUrl;
@@ -2841,8 +2965,9 @@ var Realtime = class {
2841
2965
  if (event === "realtime:error") {
2842
2966
  return;
2843
2967
  }
2844
- this.applyPresenceEvent(event, message);
2845
- this.notifyListeners(event, message);
2968
+ const normalized = normalizeChannelMeta(message);
2969
+ this.applyPresenceEvent(event, normalized);
2970
+ this.notifyListeners(event, normalized);
2846
2971
  };
2847
2972
  this.connectionAttempt = { id: attemptId, socket, cancel: fail };
2848
2973
  socket.on("connect", onConnect);
@@ -3090,6 +3215,17 @@ var Realtime = class {
3090
3215
  this.socket.emit("realtime:unsubscribe", { channel });
3091
3216
  }
3092
3217
  }
3218
+ /**
3219
+ * Publish an event to a channel.
3220
+ *
3221
+ * Delivery notes (verified against a live backend):
3222
+ * - Payload fields arrive spread onto the received message itself, next to
3223
+ * `meta` - not nested under a `payload` key. Publishing `{ text: "hi" }`
3224
+ * means receivers read `msg.text`.
3225
+ * - The sender receives its own message too. Deduplicate with
3226
+ * `msg.meta.messageId` (or `msg.meta.senderId`) if you also update local
3227
+ * state optimistically.
3228
+ */
3093
3229
  async publish(channel, event, payload) {
3094
3230
  if (!this.socket?.connected) {
3095
3231
  throw new Error(
@@ -3098,6 +3234,12 @@ var Realtime = class {
3098
3234
  }
3099
3235
  this.socket.emit("realtime:publish", { channel, event, payload });
3100
3236
  }
3237
+ /**
3238
+ * Listen for an event by name, across all subscribed channels.
3239
+ * Filter by channel inside the callback: `msg.meta.channel` always matches
3240
+ * the exact name passed to subscribe() (the SDK strips the server's
3241
+ * transport prefix before delivery).
3242
+ */
3101
3243
  on(event, callback) {
3102
3244
  const listeners = this.eventListeners.get(event) ?? /* @__PURE__ */ new Set();
3103
3245
  listeners.add(callback);
package/dist/ssr.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- import { R as ResultClient } from './client-DeE086La.cjs';
2
- import { o as ResultError, a as ResultConfig, G as AuthRefreshResponse } from './types-CbsaMttt.cjs';
3
- import { A as AuthCookieSettings, C as CookieStore, a as CookieWriter } from './middleware-BBY_6hyx.cjs';
4
- export { b as AuthCookieNames, c as AuthCookieOptions, d as CookieOptions, e as CookieReader, D as DEFAULT_ACCESS_TOKEN_COOKIE, f as DEFAULT_REFRESH_TOKEN_COOKIE, U as UpdateSessionOptions, g as UpdateSessionResult, h as accessTokenCookieOptions, i as clearAuthCookies, j as getAccessTokenCookieName, k as getRefreshTokenCookieName, r as refreshTokenCookieOptions, s as setAuthCookies, u as updateSession } from './middleware-BBY_6hyx.cjs';
1
+ import { R as ResultClient } from './client-CJv_awPt.cjs';
2
+ import { o as ResultError, a as ResultConfig, G as AuthRefreshResponse } from './types-DSVtGaIA.cjs';
3
+ import { A as AuthCookieSettings, C as CookieStore, a as CookieWriter } from './middleware-C1Z6aMvn.cjs';
4
+ export { b as AuthCookieNames, c as AuthCookieOptions, d as CookieOptions, e as CookieReader, D as DEFAULT_ACCESS_TOKEN_COOKIE, f as DEFAULT_REFRESH_TOKEN_COOKIE, U as UpdateSessionOptions, g as UpdateSessionResult, h as accessTokenCookieOptions, i as clearAuthCookies, j as getAccessTokenCookieName, k as getRefreshTokenCookieName, r as refreshTokenCookieOptions, s as setAuthCookies, u as updateSession } from './middleware-C1Z6aMvn.cjs';
5
5
  import '@supabase/postgrest-js';
6
6
 
7
7
  interface CreateAuthActionsOptions extends Omit<ResultConfig, "accessToken" | "edgeFunctionToken" | "isServerMode" | "auth">, AuthCookieSettings {
package/dist/ssr.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { R as ResultClient } from './client-Z0zUHGE3.js';
2
- import { o as ResultError, a as ResultConfig, G as AuthRefreshResponse } from './types-CbsaMttt.js';
3
- import { A as AuthCookieSettings, C as CookieStore, a as CookieWriter } from './middleware-TGaDOhE9.js';
4
- export { b as AuthCookieNames, c as AuthCookieOptions, d as CookieOptions, e as CookieReader, D as DEFAULT_ACCESS_TOKEN_COOKIE, f as DEFAULT_REFRESH_TOKEN_COOKIE, U as UpdateSessionOptions, g as UpdateSessionResult, h as accessTokenCookieOptions, i as clearAuthCookies, j as getAccessTokenCookieName, k as getRefreshTokenCookieName, r as refreshTokenCookieOptions, s as setAuthCookies, u as updateSession } from './middleware-TGaDOhE9.js';
1
+ import { R as ResultClient } from './client-DrsZ1qIm.js';
2
+ import { o as ResultError, a as ResultConfig, G as AuthRefreshResponse } from './types-DSVtGaIA.js';
3
+ import { A as AuthCookieSettings, C as CookieStore, a as CookieWriter } from './middleware-BJl9JRg3.js';
4
+ export { b as AuthCookieNames, c as AuthCookieOptions, d as CookieOptions, e as CookieReader, D as DEFAULT_ACCESS_TOKEN_COOKIE, f as DEFAULT_REFRESH_TOKEN_COOKIE, U as UpdateSessionOptions, g as UpdateSessionResult, h as accessTokenCookieOptions, i as clearAuthCookies, j as getAccessTokenCookieName, k as getRefreshTokenCookieName, r as refreshTokenCookieOptions, s as setAuthCookies, u as updateSession } from './middleware-BJl9JRg3.js';
5
5
  import '@supabase/postgrest-js';
6
6
 
7
7
  interface CreateAuthActionsOptions extends Omit<ResultConfig, "accessToken" | "edgeFunctionToken" | "isServerMode" | "auth">, AuthCookieSettings {