@howone/sdk 0.3.7 → 0.3.9

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
@@ -202,6 +202,22 @@ function useAuth() {
202
202
  setTokenState(null);
203
203
  setUser(null);
204
204
  notifyAuthStateChanged();
205
+ if (typeof window !== "undefined") {
206
+ const loc = window.location.href;
207
+ const pid = getDefaultProjectId();
208
+ try {
209
+ const root = env2.baseUrl;
210
+ const authUrl = new URL("/auth", String(root));
211
+ authUrl.searchParams.set("redirect_uri", String(loc));
212
+ if (pid) authUrl.searchParams.set("project_id", String(pid));
213
+ window.location.href = authUrl.toString();
214
+ } catch {
215
+ const encoded = encodeURIComponent(String(loc));
216
+ const pidParam = pid ? `&project_id=${encodeURIComponent(String(pid))}` : "";
217
+ const root = env2.baseUrl;
218
+ window.location.href = `${root}/auth?redirect_uri=${encoded}${pidParam}`;
219
+ }
220
+ }
205
221
  };
206
222
  return {
207
223
  token,
@@ -230,11 +246,14 @@ function notifyAuthStateChanged() {
230
246
  }
231
247
  }
232
248
  }
233
- var AUTH_TOKEN_KEY, authSubscribers;
249
+ var AUTH_TOKEN_KEY, envValue, env2, authSubscribers;
234
250
  var init_auth = __esm({
235
251
  "src/auth/index.ts"() {
236
252
  "use strict";
253
+ init_config();
237
254
  AUTH_TOKEN_KEY = "auth_token";
255
+ envValue = getGlobalEnvironment() || "prod";
256
+ env2 = setEnvironment(envValue);
238
257
  authSubscribers = /* @__PURE__ */ new Set();
239
258
  }
240
259
  });
@@ -300,8 +319,8 @@ var detectEnvironmentFromHostname = () => {
300
319
  }
301
320
  };
302
321
  var resolveApiBaseUrl = () => {
303
- const env2 = detectEnvironmentFromHostname();
304
- return API_BASE_URLS[env2] ?? API_BASE_URLS.dev;
322
+ const env3 = detectEnvironmentFromHostname();
323
+ return API_BASE_URLS[env3] ?? API_BASE_URLS.dev;
305
324
  };
306
325
  var UnifiedAuthService = class {
307
326
  constructor() {
@@ -932,7 +951,7 @@ var LoginForm = ({
932
951
 
933
952
  // src/components/auth/HowoneProvider.tsx
934
953
  init_auth();
935
- import { createContext as createContext2, useContext as useContext2, useState as useState7, useEffect as useEffect6, useMemo } from "react";
954
+ import { createContext as createContext2, useContext as useContext2, useState as useState7, useEffect as useEffect6, useMemo, useCallback as useCallback4 } from "react";
936
955
 
937
956
  // src/components/theme/ThemeProvider.tsx
938
957
  import { createContext, useContext, useEffect as useEffect3, useState as useState3 } from "react";
@@ -1304,8 +1323,8 @@ var HowOneProvider = ({
1304
1323
  }
1305
1324
  }, []);
1306
1325
  const resolvedAuthUrl = useMemo(() => {
1307
- const env2 = getGlobalEnvironment() ?? "dev";
1308
- switch (env2) {
1326
+ const env3 = getGlobalEnvironment() ?? "dev";
1327
+ switch (env3) {
1309
1328
  case "local":
1310
1329
  return "http://localhost:3000/auth";
1311
1330
  case "prod":
@@ -1325,34 +1344,42 @@ var HowOneProvider = ({
1325
1344
  injectRedirectOverlayStyles();
1326
1345
  }
1327
1346
  }, [pendingRedirect]);
1328
- useEffect6(() => {
1329
- if (!hasCheckedUrlToken) {
1330
- return;
1331
- }
1332
- if (redirectOnUnauthenticated && !token && !user) {
1347
+ const redirectToAuth = useCallback4(() => {
1348
+ if (!redirectOnUnauthenticated || typeof window === "undefined") return;
1349
+ try {
1333
1350
  const currentUrl = new URL(window.location.href);
1334
- if (!currentUrl.pathname.includes("/auth")) {
1335
- try {
1336
- const authUrlObj = new URL(resolvedAuthUrl);
1337
- const redirectUri = window.location.href;
1338
- authUrlObj.searchParams.set("redirect_uri", redirectUri);
1339
- if (projectId) {
1340
- authUrlObj.searchParams.set("project_id", projectId);
1341
- }
1342
- setPendingRedirect(true);
1343
- requestAnimationFrame(() => {
1344
- window.location.href = authUrlObj.toString();
1345
- });
1346
- } catch (error) {
1347
- console.error("[HowOneProvider] Failed to build auth URL:", error);
1348
- setPendingRedirect(true);
1349
- requestAnimationFrame(() => {
1350
- window.location.href = resolvedAuthUrl;
1351
- });
1351
+ if (currentUrl.pathname.includes("/auth")) return;
1352
+ try {
1353
+ const authUrlObj = new URL(resolvedAuthUrl);
1354
+ authUrlObj.searchParams.set("redirect_uri", window.location.href);
1355
+ if (projectId) {
1356
+ authUrlObj.searchParams.set("project_id", projectId);
1352
1357
  }
1358
+ setPendingRedirect(true);
1359
+ requestAnimationFrame(() => {
1360
+ window.location.href = authUrlObj.toString();
1361
+ });
1362
+ return;
1363
+ } catch (error) {
1364
+ console.error("[HowOneProvider] Failed to build auth URL:", error);
1353
1365
  }
1366
+ setPendingRedirect(true);
1367
+ requestAnimationFrame(() => {
1368
+ window.location.href = resolvedAuthUrl;
1369
+ });
1370
+ } catch {
1371
+ setPendingRedirect(true);
1372
+ requestAnimationFrame(() => {
1373
+ window.location.href = resolvedAuthUrl;
1374
+ });
1354
1375
  }
1355
- }, [token, user, redirectOnUnauthenticated, resolvedAuthUrl, projectId, hasCheckedUrlToken]);
1376
+ }, [redirectOnUnauthenticated, resolvedAuthUrl, projectId]);
1377
+ useEffect6(() => {
1378
+ if (!hasCheckedUrlToken) return;
1379
+ if (!token && !user) {
1380
+ redirectToAuth();
1381
+ }
1382
+ }, [token, user, hasCheckedUrlToken, redirectToAuth]);
1356
1383
  const logout = () => {
1357
1384
  try {
1358
1385
  setToken(null);
@@ -1360,6 +1387,7 @@ var HowOneProvider = ({
1360
1387
  }
1361
1388
  setTokenState(null);
1362
1389
  setUser(null);
1390
+ redirectToAuth();
1363
1391
  };
1364
1392
  const value = {
1365
1393
  user,
@@ -1678,7 +1706,7 @@ import React8 from "react";
1678
1706
  import { Icon as Icon5 } from "@iconify/react";
1679
1707
 
1680
1708
  // src/components/ui/Toast/ClayxToast.tsx
1681
- import React7, { useCallback as useCallback4 } from "react";
1709
+ import React7, { useCallback as useCallback5 } from "react";
1682
1710
  import { Bounce, toast } from "react-toastify";
1683
1711
  import { Icon as Icon4 } from "@iconify/react";
1684
1712
 
@@ -1828,7 +1856,7 @@ var TOAST_ICONS = {
1828
1856
  };
1829
1857
  var CloseButton = React7.memo(({ closeToast }) => {
1830
1858
  const { theme } = useTheme();
1831
- const handleClick = useCallback4((e) => {
1859
+ const handleClick = useCallback5((e) => {
1832
1860
  e.preventDefault();
1833
1861
  e.stopPropagation();
1834
1862
  closeToast?.();
@@ -1865,7 +1893,7 @@ CloseButton.displayName = "CloseButton";
1865
1893
  var ToastContent = ({ type, title, message, component, closeToast }) => {
1866
1894
  const iconConfig = TOAST_ICONS[type];
1867
1895
  const { theme } = useTheme();
1868
- const handleClose = useCallback4(() => {
1896
+ const handleClose = useCallback5(() => {
1869
1897
  closeToast?.();
1870
1898
  }, [closeToast]);
1871
1899
  const getTextColor = () => {
@@ -2012,7 +2040,7 @@ var createToast = (type) => {
2012
2040
  theme: getToastifyTheme(),
2013
2041
  // 确保圆角样式不被覆盖,添加 rounded-xl 类
2014
2042
  className: "!p-0 !shadow-none !rounded-xl",
2015
- style: { padding: 0, borderRadius: "0.75rem" }
2043
+ style: { padding: 0, borderRadius: "0.75rem", backgroundColor: "transparent" }
2016
2044
  }
2017
2045
  );
2018
2046
  };
@@ -2392,6 +2420,7 @@ function createArtifactsClient(req) {
2392
2420
  }
2393
2421
 
2394
2422
  // src/services/sse-executor.ts
2423
+ init_config();
2395
2424
  async function executeSSEWorkflow(request, options = {}) {
2396
2425
  const startTime = Date.now();
2397
2426
  const result = {
@@ -2480,6 +2509,18 @@ async function executeSSEWorkflow(request, options = {}) {
2480
2509
  if (rawEvent.type === "stream" && rawEvent.delta && options.onStreamContent) {
2481
2510
  options.onStreamContent(rawEvent.delta);
2482
2511
  }
2512
+ if (rawEvent.type === "key_limit_exceed") {
2513
+ const errorMsg = rawEvent.data.content;
2514
+ result.errors.push(errorMsg);
2515
+ showLimitUpgradeToast(
2516
+ "Your credits are exhausted. Please upgrade your plan to continue generating projects.",
2517
+ () => window.open(`${getEnvs().AUTH_ROOT_VALUE}/price`, "_blank")
2518
+ );
2519
+ if (options.onError) {
2520
+ options.onError(new Error(errorMsg));
2521
+ }
2522
+ throw new Error(errorMsg);
2523
+ }
2483
2524
  if (rawEvent.type === "execution_complete" && rawEvent.data) {
2484
2525
  const eventData = rawEvent.data;
2485
2526
  const eventResult = eventData.result;
@@ -2894,6 +2935,7 @@ async function executeWorkflowStreamPost(baseUrl, projectId, workflowId, request
2894
2935
  }
2895
2936
 
2896
2937
  // src/services/workflow-executor.ts
2938
+ init_config();
2897
2939
  var WorkflowExecutor = class {
2898
2940
  constructor(baseUrl, projectId, authToken) {
2899
2941
  this.baseUrl = baseUrl.replace(/\/$/, "");
@@ -2999,6 +3041,17 @@ var WorkflowExecutor = class {
2999
3041
  options.onCostUpdate(result.costStats);
3000
3042
  }
3001
3043
  }
3044
+ } else if (event.type === "key_limit_exceed") {
3045
+ const errorMsg = event.data?.content;
3046
+ result.errors.push(errorMsg);
3047
+ showLimitUpgradeToast(
3048
+ "Your credits are exhausted. Please upgrade your plan to continue generating projects.",
3049
+ () => window.open(`${getEnvs().AUTH_ROOT_VALUE}/price`, "_blank")
3050
+ );
3051
+ if (options?.onError) {
3052
+ options.onError(new Error(errorMsg));
3053
+ }
3054
+ throw new Error(errorMsg);
3002
3055
  } else if (event.type === "execution_complete" && event.data) {
3003
3056
  const completeData = event.data;
3004
3057
  const originalMessage = completeData.result?.original_message;
@@ -3138,9 +3191,9 @@ function wrapRequestWithProjectPrefix(biz, projectId) {
3138
3191
  return wrapped;
3139
3192
  }
3140
3193
  function createClient(opts) {
3141
- const envValue = opts.env || getGlobalEnvironment() || "prod";
3142
- const env2 = setEnvironment(envValue);
3143
- const actualAiBaseUrl = opts.baseUrl || env2.aiBaseUrl;
3194
+ const envValue2 = opts.env || getGlobalEnvironment() || "prod";
3195
+ const env3 = setEnvironment(envValue2);
3196
+ const actualAiBaseUrl = opts.baseUrl || env3.aiBaseUrl;
3144
3197
  function makeRequestFromBase(base) {
3145
3198
  return new request_default({
3146
3199
  baseURL: base,
@@ -3172,8 +3225,8 @@ function createClient(opts) {
3172
3225
  }
3173
3226
  });
3174
3227
  }
3175
- const biz = makeRequestFromBase(env2.baseUrl);
3176
- const ai = makeRequestFromBase(env2.aiBaseUrl);
3228
+ const biz = makeRequestFromBase(env3.baseUrl);
3229
+ const ai = makeRequestFromBase(env3.aiBaseUrl);
3177
3230
  const bizWrapped = wrapRequestWithProjectPrefix(biz, opts?.projectId);
3178
3231
  let token = null;
3179
3232
  const bootstrapToken = getGlobalAvailableToken();
@@ -3187,9 +3240,7 @@ function createClient(opts) {
3187
3240
  return getGlobalAvailableToken();
3188
3241
  }
3189
3242
  try {
3190
- if (opts?.projectId) {
3191
- setDefaultProjectId(String(opts.projectId));
3192
- }
3243
+ setDefaultProjectId(opts?.projectId ? String(opts.projectId) : null);
3193
3244
  } catch {
3194
3245
  }
3195
3246
  function applyToken(t) {
@@ -3473,7 +3524,7 @@ function createClient(opts) {
3473
3524
  if (typeof window === "undefined") return;
3474
3525
  const loc = redirect || window.location.href;
3475
3526
  try {
3476
- const root = env2.baseUrl;
3527
+ const root = env3.baseUrl;
3477
3528
  const authUrl = new URL("/auth", String(root));
3478
3529
  authUrl.searchParams.set("redirect_uri", String(loc));
3479
3530
  if (opts?.projectId) authUrl.searchParams.set("project_id", String(opts.projectId));
@@ -3481,7 +3532,7 @@ function createClient(opts) {
3481
3532
  } catch {
3482
3533
  const encoded = encodeURIComponent(String(loc));
3483
3534
  const pid = opts?.projectId ? `&project_id=${encodeURIComponent(String(opts.projectId))}` : "";
3484
- const root = env2.baseUrl;
3535
+ const root = env3.baseUrl;
3485
3536
  window.location.href = `${root}/auth?redirect_uri=${encoded}${pid}`;
3486
3537
  }
3487
3538
  },
@@ -3490,6 +3541,21 @@ function createClient(opts) {
3490
3541
  applyToken(null);
3491
3542
  rememberExternalToken(null, 0);
3492
3543
  pendingExternalTokenPromise = null;
3544
+ if (typeof window !== "undefined") {
3545
+ const loc = window.location.href;
3546
+ try {
3547
+ const root = env3.baseUrl;
3548
+ const authUrl = new URL("/auth", String(root));
3549
+ authUrl.searchParams.set("redirect_uri", String(loc));
3550
+ if (opts?.projectId) authUrl.searchParams.set("project_id", String(opts.projectId));
3551
+ window.location.href = authUrl.toString();
3552
+ } catch {
3553
+ const encoded = encodeURIComponent(String(loc));
3554
+ const pid = opts?.projectId ? `&project_id=${encodeURIComponent(String(opts.projectId))}` : "";
3555
+ const root = env3.baseUrl;
3556
+ window.location.href = `${root}/auth?redirect_uri=${encoded}${pid}`;
3557
+ }
3558
+ }
3493
3559
  }
3494
3560
  },
3495
3561
  sanitizeUrl: (o) => {
@@ -3535,7 +3601,7 @@ function useDebounce(value, delay) {
3535
3601
  }
3536
3602
 
3537
3603
  // src/hooks/use-workflow-stream.ts
3538
- import { useState as useState11, useCallback as useCallback5, useRef as useRef2 } from "react";
3604
+ import { useState as useState11, useCallback as useCallback6, useRef as useRef2 } from "react";
3539
3605
  function useWorkflowStream() {
3540
3606
  const [state, setState] = useState11({
3541
3607
  loading: false,
@@ -3546,7 +3612,7 @@ function useWorkflowStream() {
3546
3612
  error: null
3547
3613
  });
3548
3614
  const abortControllerRef = useRef2(null);
3549
- const execute = useCallback5(async (executeWorkflowStream, workflowId, inputs) => {
3615
+ const execute = useCallback6(async (executeWorkflowStream, workflowId, inputs) => {
3550
3616
  setState({
3551
3617
  loading: true,
3552
3618
  progress: 0,
@@ -3599,7 +3665,7 @@ function useWorkflowStream() {
3599
3665
  throw error;
3600
3666
  }
3601
3667
  }, []);
3602
- const cancel = useCallback5(() => {
3668
+ const cancel = useCallback6(() => {
3603
3669
  if (abortControllerRef.current) {
3604
3670
  abortControllerRef.current.abort();
3605
3671
  setState((prev) => ({
@@ -3609,7 +3675,7 @@ function useWorkflowStream() {
3609
3675
  }));
3610
3676
  }
3611
3677
  }, []);
3612
- const reset = useCallback5(() => {
3678
+ const reset = useCallback6(() => {
3613
3679
  setState({
3614
3680
  loading: false,
3615
3681
  progress: 0,