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