@omnikit-ai/sdk 2.2.0 → 2.2.1

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.mjs CHANGED
@@ -658,6 +658,20 @@ var APIClient = class {
658
658
  description: "Create a signed URL for a private file",
659
659
  method: "POST",
660
660
  params: { file_uri: "string" }
661
+ },
662
+ {
663
+ name: "DownloadPrivateFile",
664
+ path: "/services/files/private/download",
665
+ description: "Download a private file via backend proxy (solves CORS issues)",
666
+ method: "POST",
667
+ params: { file_uri: "string" }
668
+ },
669
+ {
670
+ name: "DownloadFile",
671
+ path: "/services/files/{file_id}/download",
672
+ description: "Download a public file via backend proxy (like Supabase ?download)",
673
+ method: "GET",
674
+ params: { file_id: "string", download: "boolean", filename: "string" }
661
675
  }
662
676
  ];
663
677
  builtInServices.forEach((service) => {
@@ -867,6 +881,25 @@ var APIClient = class {
867
881
  }
868
882
  return this._connectors;
869
883
  }
884
+ /**
885
+ * Resolve a return URL to an absolute URL.
886
+ * Handles relative paths like "/profile" by combining with current location.
887
+ * This fixes the OAuth redirect bug where relative URLs like "/profile" become
888
+ * "https://omnikit.ai/profile" instead of "https://omnikit.ai/app-builder/{id}/preview/profile"
889
+ */
890
+ _resolveReturnUrl(returnUrl) {
891
+ if (typeof window === "undefined") return returnUrl || "/";
892
+ if (!returnUrl) return window.location.href;
893
+ if (returnUrl.startsWith("http://") || returnUrl.startsWith("https://")) {
894
+ return returnUrl;
895
+ }
896
+ if (returnUrl.startsWith("/")) {
897
+ const basePath = window.location.pathname.endsWith("/") ? window.location.pathname.slice(0, -1) : window.location.pathname;
898
+ return window.location.origin + basePath + returnUrl;
899
+ }
900
+ const base = window.location.origin + window.location.pathname;
901
+ return base.endsWith("/") ? base + returnUrl : base + "/" + returnUrl;
902
+ }
870
903
  /**
871
904
  * Create auth proxy that auto-initializes
872
905
  */
@@ -894,31 +927,42 @@ var APIClient = class {
894
927
  client.emitUserChange(response);
895
928
  return response;
896
929
  },
897
- login(returnUrl) {
898
- const fullReturnUrl = returnUrl || (typeof window !== "undefined" ? window.location.href : "/");
899
- if (typeof window !== "undefined") {
900
- if (window.__omnikit_openLoginModal) {
901
- window.__omnikit_openLoginModal(fullReturnUrl);
902
- return;
903
- }
904
- const encodedReturnUrl = encodeURIComponent(fullReturnUrl);
905
- const currentPath = window.location.pathname;
906
- const apiSitesMatch = currentPath.match(/^\/api\/sites\/([^\/]+)/);
907
- if (apiSitesMatch) {
908
- window.location.href = `/api/sites/${client.appId}/login?return_url=${encodedReturnUrl}`;
909
- } else {
910
- window.location.href = `/login?return_url=${encodedReturnUrl}`;
930
+ async login(returnUrl) {
931
+ if (typeof window === "undefined") return;
932
+ const fullReturnUrl = client._resolveReturnUrl(returnUrl);
933
+ const token = getAccessToken();
934
+ if (token) {
935
+ try {
936
+ const isAuth = await this.isAuthenticated();
937
+ if (isAuth && returnUrl) {
938
+ window.location.href = fullReturnUrl;
939
+ return;
940
+ }
941
+ } catch {
911
942
  }
912
943
  }
944
+ if (window.__omnikit_openLoginModal) {
945
+ window.__omnikit_openLoginModal(fullReturnUrl);
946
+ return;
947
+ }
948
+ const encodedReturnUrl = encodeURIComponent(fullReturnUrl);
949
+ const currentPath = window.location.pathname;
950
+ const apiSitesMatch = currentPath.match(/^\/api\/sites\/([^\/]+)/);
951
+ if (apiSitesMatch) {
952
+ window.location.href = `/api/sites/${client.appId}/login?return_url=${encodedReturnUrl}`;
953
+ } else {
954
+ window.location.href = `/login?return_url=${encodedReturnUrl}`;
955
+ }
913
956
  },
914
957
  /**
915
958
  * Request a passwordless login code to email
916
959
  */
917
960
  async requestLoginCode(email, returnUrl) {
961
+ const fullReturnUrl = returnUrl ? client._resolveReturnUrl(returnUrl) : void 0;
918
962
  return await client.makeRequest(
919
963
  `${client.baseUrl}/auth/email/request-code`,
920
964
  "POST",
921
- { email, return_url: returnUrl }
965
+ { email, return_url: fullReturnUrl }
922
966
  );
923
967
  },
924
968
  /**
@@ -966,44 +1010,43 @@ var APIClient = class {
966
1010
  * Redirects to the backend OAuth endpoint for the specified provider
967
1011
  */
968
1012
  loginWithProvider(providerId, returnUrl) {
969
- const currentUrl = returnUrl || (typeof window !== "undefined" ? window.location.href : "/");
970
- const redirectUrl = `${client.baseUrl}/auth/${providerId}?redirect_url=${encodeURIComponent(currentUrl)}`;
971
- if (typeof window !== "undefined") {
972
- const inIframe = window.self !== window.top;
973
- if (inIframe) {
974
- const width = 600;
975
- const height = 700;
976
- const left = window.screen.width / 2 - width / 2;
977
- const top = window.screen.height / 2 - height / 2;
978
- const popup = window.open(
979
- redirectUrl,
980
- "oauth_popup",
981
- `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes,status=yes`
982
- );
983
- if (popup) {
984
- const checkTimer = setInterval(() => {
985
- const token = getAccessToken();
986
- if (token) {
987
- clearInterval(checkTimer);
988
- popup.close();
1013
+ if (typeof window === "undefined") {
1014
+ throw new OmnikitError("loginWithProvider() can only be called in browser environment", 400, "NOT_BROWSER");
1015
+ }
1016
+ const fullReturnUrl = client._resolveReturnUrl(returnUrl);
1017
+ const redirectUrl = `${client.baseUrl}/auth/${providerId}?redirect_url=${encodeURIComponent(fullReturnUrl)}`;
1018
+ const inIframe = window.self !== window.top;
1019
+ if (inIframe) {
1020
+ const width = 600;
1021
+ const height = 700;
1022
+ const left = window.screen.width / 2 - width / 2;
1023
+ const top = window.screen.height / 2 - height / 2;
1024
+ const popup = window.open(
1025
+ redirectUrl,
1026
+ "oauth_popup",
1027
+ `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes,status=yes`
1028
+ );
1029
+ if (popup) {
1030
+ const checkTimer = setInterval(() => {
1031
+ const token = getAccessToken();
1032
+ if (token) {
1033
+ clearInterval(checkTimer);
1034
+ popup.close();
1035
+ window.location.reload();
1036
+ return;
1037
+ }
1038
+ if (popup.closed) {
1039
+ clearInterval(checkTimer);
1040
+ const finalToken = getAccessToken();
1041
+ if (finalToken) {
989
1042
  window.location.reload();
990
- return;
991
1043
  }
992
- if (popup.closed) {
993
- clearInterval(checkTimer);
994
- const finalToken = getAccessToken();
995
- if (finalToken) {
996
- window.location.reload();
997
- }
998
- }
999
- }, 1e3);
1000
- return;
1001
- }
1044
+ }
1045
+ }, 1e3);
1046
+ return;
1002
1047
  }
1003
- window.location.href = redirectUrl;
1004
- } else {
1005
- throw new OmnikitError("loginWithProvider() can only be called in browser environment", 400, "NOT_BROWSER");
1006
1048
  }
1049
+ window.location.href = redirectUrl;
1007
1050
  },
1008
1051
  /**
1009
1052
  * Initiate Google OAuth Login
@@ -1215,7 +1258,8 @@ Example: await ${collectionName}.list({ limit: 100, sort: '-created_at' })`,
1215
1258
  // Remove callback functions from request body
1216
1259
  onToken: void 0,
1217
1260
  onComplete: void 0,
1218
- onError: void 0
1261
+ onError: void 0,
1262
+ onToolCall: void 0
1219
1263
  };
1220
1264
  Object.keys(requestBody).forEach((key) => {
1221
1265
  if (requestBody[key] === void 0) {
@@ -1266,6 +1310,14 @@ Example: await ${collectionName}.list({ limit: 100, sort: '-created_at' })`,
1266
1310
  if (event.type === "token" && event.content) {
1267
1311
  fullResponse += event.content;
1268
1312
  params.onToken?.(event.content);
1313
+ } else if (event.type === "tool_call") {
1314
+ if (params.onToolCall && event.id && event.name) {
1315
+ params.onToolCall({
1316
+ id: event.id,
1317
+ name: event.name,
1318
+ arguments: event.arguments || {}
1319
+ });
1320
+ }
1269
1321
  } else if (event.type === "done") {
1270
1322
  params.onComplete?.({
1271
1323
  result: event.result || fullResponse,
@@ -1324,6 +1376,56 @@ Example: await ${collectionName}.list({ limit: 100, sort: '-created_at' })`,
1324
1376
  );
1325
1377
  };
1326
1378
  }
1379
+ if (normalizedName === "DownloadFile") {
1380
+ return async function(params) {
1381
+ await client.ensureInitialized();
1382
+ if (!params?.file_id) {
1383
+ throw new OmnikitError(
1384
+ "file_id is required for DownloadFile",
1385
+ 400,
1386
+ "MISSING_FILE_ID"
1387
+ );
1388
+ }
1389
+ const downloadUrl = new URL(`${client.baseUrl}/apps/${client.appId}/services/files/${params.file_id}/download`);
1390
+ if (params.download !== void 0) {
1391
+ downloadUrl.searchParams.set("download", String(params.download));
1392
+ }
1393
+ if (params.filename) {
1394
+ downloadUrl.searchParams.set("filename", params.filename);
1395
+ }
1396
+ const response = await fetch(downloadUrl.toString(), {
1397
+ method: "GET"
1398
+ });
1399
+ if (!response.ok) {
1400
+ const error = await response.json().catch(() => ({ detail: "Download failed" }));
1401
+ throw new OmnikitError(
1402
+ error.detail || "Download failed",
1403
+ response.status,
1404
+ "DOWNLOAD_FAILED"
1405
+ );
1406
+ }
1407
+ const blob = await response.blob();
1408
+ const blobUrl = URL.createObjectURL(blob);
1409
+ let filename = params.filename;
1410
+ if (!filename) {
1411
+ const contentDisposition = response.headers.get("Content-Disposition");
1412
+ if (contentDisposition) {
1413
+ const match = contentDisposition.match(/filename="?([^"]+)"?/);
1414
+ if (match) filename = match[1];
1415
+ }
1416
+ }
1417
+ if (!filename) {
1418
+ filename = `file-${params.file_id}`;
1419
+ }
1420
+ const link = document.createElement("a");
1421
+ link.href = blobUrl;
1422
+ link.download = filename;
1423
+ document.body.appendChild(link);
1424
+ link.click();
1425
+ document.body.removeChild(link);
1426
+ URL.revokeObjectURL(blobUrl);
1427
+ };
1428
+ }
1327
1429
  if (normalizedName === "DownloadPrivateFile") {
1328
1430
  return async function(params) {
1329
1431
  await client.ensureInitialized();
@@ -1334,16 +1436,47 @@ Example: await ${collectionName}.list({ limit: 100, sort: '-created_at' })`,
1334
1436
  "MISSING_FILE_URI"
1335
1437
  );
1336
1438
  }
1337
- const downloadUrl = new URL(`${client.baseUrl}/apps/${client.appId}/services/files/download`);
1338
- downloadUrl.searchParams.set("file_uri", params.file_uri);
1339
- if (params.filename) {
1340
- downloadUrl.searchParams.set("filename", params.filename);
1341
- }
1439
+ const downloadUrl = `${client.baseUrl}/apps/${client.appId}/services/files/private/download`;
1342
1440
  const token = client.getAuthToken();
1343
- if (token) {
1344
- downloadUrl.searchParams.set("token", token);
1441
+ const response = await fetch(downloadUrl, {
1442
+ method: "POST",
1443
+ headers: {
1444
+ "Content-Type": "application/json",
1445
+ ...token ? { "Authorization": `Bearer ${token}` } : {}
1446
+ },
1447
+ body: JSON.stringify({ file_uri: params.file_uri })
1448
+ });
1449
+ if (!response.ok) {
1450
+ const error = await response.json().catch(() => ({ detail: "Download failed" }));
1451
+ throw new OmnikitError(
1452
+ error.detail || "Download failed",
1453
+ response.status,
1454
+ "DOWNLOAD_FAILED"
1455
+ );
1456
+ }
1457
+ const blob = await response.blob();
1458
+ const blobUrl = URL.createObjectURL(blob);
1459
+ let filename = params.filename;
1460
+ if (!filename) {
1461
+ const contentDisposition = response.headers.get("Content-Disposition");
1462
+ if (contentDisposition) {
1463
+ const match = contentDisposition.match(/filename="?([^"]+)"?/);
1464
+ if (match) filename = match[1];
1465
+ }
1466
+ }
1467
+ if (!filename) {
1468
+ const uriParts = params.file_uri.split("/");
1469
+ const lastPart = uriParts[uriParts.length - 1];
1470
+ const underscoreIdx = lastPart.indexOf("_");
1471
+ filename = underscoreIdx > 0 ? lastPart.slice(underscoreIdx + 1) : lastPart;
1345
1472
  }
1346
- window.open(downloadUrl.toString(), "_blank");
1473
+ const link = document.createElement("a");
1474
+ link.href = blobUrl;
1475
+ link.download = filename;
1476
+ document.body.appendChild(link);
1477
+ link.click();
1478
+ document.body.removeChild(link);
1479
+ URL.revokeObjectURL(blobUrl);
1347
1480
  };
1348
1481
  }
1349
1482
  return async function(params, asyncOptions) {
@@ -1362,7 +1495,7 @@ Example: await ${collectionName}.list({ limit: 100, sort: '-created_at' })`,
1362
1495
  response = await method(params, useServiceToken);
1363
1496
  } else {
1364
1497
  throw new OmnikitError(
1365
- `Service '${serviceName}' not found. Known services: SendEmail, InvokeLLM, GenerateImage, GenerateSpeech, GenerateVideo, ExtractData, SendSMS, UploadFile, UploadPrivateFile, CreateFileSignedUrl (camelCase also supported)`,
1498
+ `Service '${serviceName}' not found. Known services: SendEmail, InvokeLLM, GenerateImage, GenerateSpeech, GenerateVideo, ExtractData, SendSMS, UploadFile, UploadPrivateFile, CreateFileSignedUrl, DownloadFile, DownloadPrivateFile (camelCase also supported)`,
1366
1499
  404,
1367
1500
  "SERVICE_NOT_FOUND"
1368
1501
  );
@@ -1878,6 +2011,8 @@ Example: await ${collectionName}.list({ limit: 100, sort: '-created_at' })`,
1878
2011
  "files": "UploadFile",
1879
2012
  "files/private": "UploadPrivateFile",
1880
2013
  "files/signed-url": "CreateFileSignedUrl",
2014
+ "files/private/download": "DownloadPrivateFile",
2015
+ "files/download": "DownloadFile",
1881
2016
  "images": "GenerateImage",
1882
2017
  "speech": "GenerateSpeech",
1883
2018
  "video": "GenerateVideo",