@howone/sdk 0.6.0 → 0.7.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.d.mts +34 -10
- package/dist/index.d.ts +34 -10
- package/dist/index.js +1064 -745
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1033 -717
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -6
package/dist/index.js
CHANGED
|
@@ -164,7 +164,20 @@ function decodeJwtPayload(token) {
|
|
|
164
164
|
if (pad === 2) base64 += "==";
|
|
165
165
|
else if (pad === 3) base64 += "=";
|
|
166
166
|
else if (pad !== 0) return null;
|
|
167
|
-
const
|
|
167
|
+
const binary = atob(base64);
|
|
168
|
+
let json = binary;
|
|
169
|
+
try {
|
|
170
|
+
if (typeof TextDecoder !== "undefined") {
|
|
171
|
+
const bytes = Uint8Array.from(binary, (ch) => ch.charCodeAt(0));
|
|
172
|
+
json = new TextDecoder("utf-8", { fatal: false }).decode(bytes);
|
|
173
|
+
} else {
|
|
174
|
+
json = decodeURIComponent(
|
|
175
|
+
binary.split("").map((ch) => `%${ch.charCodeAt(0).toString(16).padStart(2, "0")}`).join("")
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
} catch {
|
|
179
|
+
json = binary;
|
|
180
|
+
}
|
|
168
181
|
return JSON.parse(json);
|
|
169
182
|
} catch {
|
|
170
183
|
return null;
|
|
@@ -284,13 +297,14 @@ var index_exports = {};
|
|
|
284
297
|
__export(index_exports, {
|
|
285
298
|
AUTH_TOKEN_KEY: () => AUTH_TOKEN_KEY,
|
|
286
299
|
ClayxButton: () => ClayxButton,
|
|
300
|
+
ClayxToast: () => ClayxToast,
|
|
301
|
+
DEFAULT_LIMIT_EXCEEDED_MESSAGE: () => DEFAULT_LIMIT_EXCEEDED_MESSAGE,
|
|
287
302
|
DefaultErrorFallback: () => DefaultErrorFallback,
|
|
288
303
|
ElementSelector: () => ElementSelector,
|
|
289
304
|
ElementSelectorProvider: () => ElementSelectorProvider,
|
|
290
305
|
ErrorBoundary: () => ErrorBoundary,
|
|
291
306
|
FloatingButton: () => FloatingButton,
|
|
292
307
|
GlobalToastContainer: () => GlobalToastContainer,
|
|
293
|
-
GoeyToast: () => GoeyToast,
|
|
294
308
|
HowOneProvider: () => HowOneProvider,
|
|
295
309
|
Loading: () => Loading,
|
|
296
310
|
LoadingSpinner: () => LoadingSpinner,
|
|
@@ -314,11 +328,13 @@ __export(index_exports, {
|
|
|
314
328
|
getEnvs: () => getEnvs,
|
|
315
329
|
getGlobalEnvironment: () => getGlobalEnvironment,
|
|
316
330
|
getToken: () => getToken,
|
|
331
|
+
handleLimitExceeded: () => handleLimitExceeded,
|
|
317
332
|
howone: () => client_default,
|
|
318
333
|
iframeNavigation: () => iframeNavigation,
|
|
319
334
|
initIframeNavigation: () => initIframeNavigation,
|
|
320
335
|
isTokenValid: () => isTokenValid,
|
|
321
336
|
loginWithEmailCode: () => loginWithEmailCode,
|
|
337
|
+
mergeLimitExceededOptions: () => mergeLimitExceededOptions,
|
|
322
338
|
onAuthStateChanged: () => onAuthStateChanged,
|
|
323
339
|
parseUserFromToken: () => parseUserFromToken,
|
|
324
340
|
sendElementSelectionToParent: () => sendElementSelectionToParent,
|
|
@@ -818,162 +834,511 @@ function getCodeStatus(email) {
|
|
|
818
834
|
return unifiedAuth.getCodeStatus(email);
|
|
819
835
|
}
|
|
820
836
|
|
|
821
|
-
// src/
|
|
822
|
-
var
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
} else {
|
|
862
|
-
newErrors.form = errorObj.data.message;
|
|
863
|
-
}
|
|
864
|
-
} else if (errorObj.msg) {
|
|
865
|
-
newErrors.form = errorObj.msg;
|
|
866
|
-
} else if (errorObj.data?.message) {
|
|
867
|
-
newErrors.form = errorObj.data.message;
|
|
868
|
-
} else {
|
|
869
|
-
newErrors.form = "\u53D1\u751F\u672A\u77E5\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5";
|
|
870
|
-
}
|
|
871
|
-
setValidationErrors(newErrors);
|
|
872
|
-
} catch (e) {
|
|
873
|
-
setValidationErrors({ form: loginError });
|
|
837
|
+
// src/services/ai-workflow.ts
|
|
838
|
+
var AIWorkflowClient = class {
|
|
839
|
+
constructor(options = {}) {
|
|
840
|
+
this.baseUrl = options.baseUrl?.replace(/\/+$/, "") || "";
|
|
841
|
+
this.apiKey = options.apiKey;
|
|
842
|
+
this.headers = { "Content-Type": "application/json", ...options.headers || {} };
|
|
843
|
+
this.fetchImpl = options.fetchImpl || fetch.bind(globalThis);
|
|
844
|
+
}
|
|
845
|
+
buildHeaders(extra) {
|
|
846
|
+
const h = { ...this.headers, ...extra || {} };
|
|
847
|
+
if (this.apiKey && !h["Authorization"]) {
|
|
848
|
+
h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
849
|
+
}
|
|
850
|
+
return h;
|
|
851
|
+
}
|
|
852
|
+
async safeJson(resp) {
|
|
853
|
+
try {
|
|
854
|
+
return await resp.json();
|
|
855
|
+
} catch (_e) {
|
|
856
|
+
return null;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* 按 ID 执行工作流:POST {baseUrl}/workflow/{workflowId}/execute
|
|
861
|
+
* body: { input, options }
|
|
862
|
+
*/
|
|
863
|
+
async executeWorkflow(workflowId, inputs, options) {
|
|
864
|
+
if (!this.baseUrl) {
|
|
865
|
+
throw new Error("AI workflow client requires a baseUrl (e.g. https://evoagentx-server.fly.dev)");
|
|
866
|
+
}
|
|
867
|
+
const url = `${this.baseUrl}/workflow/${workflowId}/execute`;
|
|
868
|
+
try {
|
|
869
|
+
const res = await this.fetchImpl(url, {
|
|
870
|
+
method: "POST",
|
|
871
|
+
headers: this.buildHeaders(),
|
|
872
|
+
body: JSON.stringify({ inputs, options })
|
|
873
|
+
});
|
|
874
|
+
const data = await this.safeJson(res);
|
|
875
|
+
if (!res.ok) {
|
|
876
|
+
return { success: false, error: data?.error || `HTTP ${res.status}` };
|
|
874
877
|
}
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
return () => clearTimeout(timer);
|
|
878
|
+
return data || { success: true };
|
|
879
|
+
} catch (error) {
|
|
880
|
+
return { success: false, error: error instanceof Error ? error.message : "Network error" };
|
|
879
881
|
}
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
function createAIWorkflowClient(options = {}) {
|
|
885
|
+
return new AIWorkflowClient(options);
|
|
886
|
+
}
|
|
887
|
+
var aiWorkflow = createAIWorkflowClient({ baseUrl: "https://evoagentx-server" });
|
|
888
|
+
|
|
889
|
+
// src/services/request/index.ts
|
|
890
|
+
var import_axios = __toESM(require("axios"));
|
|
891
|
+
var Request = class {
|
|
892
|
+
constructor(config) {
|
|
893
|
+
this.abortControllers = /* @__PURE__ */ new Map();
|
|
894
|
+
this.instance = import_axios.default.create({
|
|
895
|
+
...config,
|
|
896
|
+
withCredentials: true,
|
|
897
|
+
validateStatus: (status) => {
|
|
898
|
+
return status >= 200 && status < 300;
|
|
890
899
|
}
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
900
|
+
});
|
|
901
|
+
this.interceptors = config.interceptors;
|
|
902
|
+
this.instance.interceptors.request.use(
|
|
903
|
+
this.interceptors?.requestInterceptor,
|
|
904
|
+
this.interceptors?.requestInterceptorCatch
|
|
905
|
+
);
|
|
906
|
+
this.instance.interceptors.response.use(
|
|
907
|
+
this.interceptors?.responseInterceptor,
|
|
908
|
+
this.interceptors?.responseInterceptorCatch
|
|
909
|
+
);
|
|
910
|
+
this.instance.interceptors.request.use(
|
|
911
|
+
(config2) => {
|
|
912
|
+
return config2;
|
|
913
|
+
},
|
|
914
|
+
(err) => {
|
|
915
|
+
return Promise.reject(err);
|
|
899
916
|
}
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
917
|
+
);
|
|
918
|
+
this.instance.interceptors.response.use(
|
|
919
|
+
(res) => {
|
|
920
|
+
return res.data;
|
|
921
|
+
},
|
|
922
|
+
(err) => {
|
|
923
|
+
if (import_axios.default.isCancel(err)) {
|
|
924
|
+
return Promise.reject({
|
|
925
|
+
isCanceled: true,
|
|
926
|
+
message: "request canceled",
|
|
927
|
+
originalError: err
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
if (err.response?.data?.error) {
|
|
931
|
+
return Promise.reject(err.response.data.error);
|
|
932
|
+
}
|
|
933
|
+
return Promise.reject(err);
|
|
905
934
|
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
935
|
+
);
|
|
936
|
+
}
|
|
937
|
+
cancelRequest(url) {
|
|
938
|
+
this.abortControllers.forEach((controller, key) => {
|
|
939
|
+
if (key.includes(url)) {
|
|
940
|
+
controller.abort();
|
|
941
|
+
this.abortControllers.delete(key);
|
|
913
942
|
}
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
cancelAllRequests() {
|
|
946
|
+
this.abortControllers.forEach((controller) => {
|
|
947
|
+
controller.abort();
|
|
948
|
+
});
|
|
949
|
+
this.abortControllers.clear();
|
|
950
|
+
}
|
|
951
|
+
request(config) {
|
|
952
|
+
const controller = new AbortController();
|
|
953
|
+
const url = config.url || "";
|
|
954
|
+
const method = config.method || "GET";
|
|
955
|
+
const key = `${method}:${url}`;
|
|
956
|
+
this.abortControllers.set(key, controller);
|
|
957
|
+
config.signal = controller.signal;
|
|
958
|
+
return new Promise((resolve, reject) => {
|
|
959
|
+
if (config.interceptors?.requestInterceptor) {
|
|
960
|
+
config = config.interceptors.requestInterceptor(config);
|
|
961
|
+
}
|
|
962
|
+
this.instance.request(config).then((res) => {
|
|
963
|
+
this.abortControllers.delete(key);
|
|
964
|
+
if (config.interceptors?.responseInterceptor) {
|
|
965
|
+
res = config.interceptors.responseInterceptor(res);
|
|
966
|
+
}
|
|
967
|
+
resolve(res);
|
|
968
|
+
}).catch((err) => {
|
|
969
|
+
this.abortControllers.delete(key);
|
|
970
|
+
reject(err);
|
|
971
|
+
});
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
get(config) {
|
|
975
|
+
return this.request({ ...config, method: "GET" });
|
|
976
|
+
}
|
|
977
|
+
post(config) {
|
|
978
|
+
return this.request({ ...config, method: "POST" });
|
|
979
|
+
}
|
|
980
|
+
delete(config) {
|
|
981
|
+
return this.request({ ...config, method: "DELETE" });
|
|
982
|
+
}
|
|
983
|
+
put(config) {
|
|
984
|
+
return this.request({ ...config, method: "PUT" });
|
|
985
|
+
}
|
|
986
|
+
patch(config) {
|
|
987
|
+
return this.request({ ...config, method: "PATCH" });
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
var request_default = Request;
|
|
991
|
+
|
|
992
|
+
// src/services/ai-workflow-axios.ts
|
|
993
|
+
function createAIWorkflowClientAxios(options = {}) {
|
|
994
|
+
const basePath = options.basePath ?? "/api";
|
|
995
|
+
const baseUrl = (options.baseUrl || "https://evoagentx-server.fly.dev").replace(/\/+$/, "");
|
|
996
|
+
const baseAPI = `${baseUrl}${basePath.startsWith("/") ? "" : "/"}${basePath}`.replace(/\/+$/, "");
|
|
997
|
+
const client = options.requestInstance || new request_default({
|
|
998
|
+
baseURL: baseAPI,
|
|
999
|
+
timeout: options.timeout ?? 6e4,
|
|
1000
|
+
interceptors: {
|
|
1001
|
+
requestInterceptor: (config) => {
|
|
1002
|
+
config.headers = config.headers || {};
|
|
1003
|
+
if (options.apiKey && !config.headers["Authorization"]) {
|
|
1004
|
+
config.headers["Authorization"] = `Bearer ${options.apiKey}`;
|
|
1005
|
+
}
|
|
1006
|
+
if (options.headers) {
|
|
1007
|
+
config.headers = { ...config.headers || {}, ...options.headers };
|
|
1008
|
+
}
|
|
1009
|
+
return config;
|
|
1010
|
+
},
|
|
1011
|
+
requestInterceptorCatch: (err) => Promise.reject(err),
|
|
1012
|
+
responseInterceptor: (res) => res,
|
|
1013
|
+
responseInterceptorCatch: (err) => Promise.reject(err)
|
|
1014
|
+
}
|
|
1015
|
+
});
|
|
1016
|
+
return {
|
|
1017
|
+
async executeWorkflow(workflowId, inputs, opts) {
|
|
1018
|
+
const url = `${baseUrl}/workflow/${workflowId}/execute`;
|
|
1019
|
+
const data = await client.post({ url, data: { inputs, options: opts } });
|
|
1020
|
+
return data;
|
|
1021
|
+
}
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
// src/services/artifact-types.ts
|
|
1026
|
+
function canAccessArtifact(a, ctx = {}) {
|
|
1027
|
+
if (!a) return false;
|
|
1028
|
+
if (a.visibility === "public") return true;
|
|
1029
|
+
if (a.visibility === "project") {
|
|
1030
|
+
if (ctx.projectId && a.projectId && ctx.projectId === a.projectId) return true;
|
|
1031
|
+
if (ctx.tokenScopes && ctx.tokenScopes.includes("project:read")) return true;
|
|
1032
|
+
return false;
|
|
1033
|
+
}
|
|
1034
|
+
if (a.visibility === "private") {
|
|
1035
|
+
if (ctx.userId && a.ownerId && ctx.userId === a.ownerId) return true;
|
|
1036
|
+
if (ctx.tokenScopes && (ctx.tokenScopes.includes("artifact:read:all") || ctx.tokenScopes.includes("admin"))) return true;
|
|
1037
|
+
return false;
|
|
1038
|
+
}
|
|
1039
|
+
if (a.visibility === "shared") {
|
|
1040
|
+
if (ctx.userId && a.sharedWith && a.sharedWith.includes(ctx.userId)) return true;
|
|
1041
|
+
if (ctx.tokenScopes && (ctx.tokenScopes.includes("artifact:read:all") || ctx.tokenScopes.includes("admin"))) return true;
|
|
1042
|
+
return false;
|
|
1043
|
+
}
|
|
1044
|
+
return false;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
// src/services/artifacts-client.ts
|
|
1048
|
+
function createArtifactsClient(req) {
|
|
1049
|
+
return {
|
|
1050
|
+
async create(input) {
|
|
1051
|
+
return await req.post({ url: "/artifacts", data: input });
|
|
1052
|
+
},
|
|
1053
|
+
async list(query) {
|
|
1054
|
+
return await req.get({ url: "/artifacts", params: query });
|
|
1055
|
+
},
|
|
1056
|
+
async get(id) {
|
|
1057
|
+
return await req.get({ url: `/artifacts/${encodeURIComponent(id)}` });
|
|
1058
|
+
},
|
|
1059
|
+
async setVisibility(id, visibility) {
|
|
1060
|
+
await req.patch({ url: `/artifacts/${encodeURIComponent(id)}/visibility`, data: { visibility } });
|
|
1061
|
+
},
|
|
1062
|
+
async delete(id) {
|
|
1063
|
+
await req.delete({ url: `/artifacts/${encodeURIComponent(id)}` });
|
|
1064
|
+
},
|
|
1065
|
+
// convenience local check (server is authoritative)
|
|
1066
|
+
canAccessLocal(a, ctx) {
|
|
1067
|
+
if (!a) return false;
|
|
1068
|
+
if (a.visibility === "public") return true;
|
|
1069
|
+
if (a.visibility === "project") return Boolean(ctx.projectId && a.projectId && ctx.projectId === a.projectId);
|
|
1070
|
+
if (a.visibility === "private") return Boolean(ctx.userId && a.ownerId && ctx.userId === a.ownerId);
|
|
1071
|
+
if (a.visibility === "shared") return Boolean(ctx.userId && a.sharedWith && a.sharedWith.includes(ctx.userId));
|
|
1072
|
+
return false;
|
|
1073
|
+
}
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
// src/services/upload-client.ts
|
|
1078
|
+
function createUploadClient(req, projectId) {
|
|
1079
|
+
const uploadUrl = projectId ? `/entities/apps/${projectId}/files` : "/files";
|
|
1080
|
+
return {
|
|
1081
|
+
/**
|
|
1082
|
+
* 上传单个文件
|
|
1083
|
+
*
|
|
1084
|
+
* @example
|
|
1085
|
+
* ```typescript
|
|
1086
|
+
* const { url } = await client.upload.file(imageFile)
|
|
1087
|
+
* console.log('文件地址:', url)
|
|
1088
|
+
* ```
|
|
1089
|
+
*/
|
|
1090
|
+
async file(file, options) {
|
|
1091
|
+
const formData = new FormData();
|
|
1092
|
+
if (typeof file === "string") {
|
|
1093
|
+
if (file.startsWith("data:")) {
|
|
1094
|
+
const response2 = await fetch(file);
|
|
1095
|
+
const blob = await response2.blob();
|
|
1096
|
+
formData.append("file", blob, "upload.bin");
|
|
1097
|
+
} else {
|
|
1098
|
+
formData.append("fileUrl", file);
|
|
1099
|
+
}
|
|
1100
|
+
} else if (file instanceof File) {
|
|
1101
|
+
formData.append("file", file, file.name);
|
|
1102
|
+
} else {
|
|
1103
|
+
formData.append("file", file, "upload.bin");
|
|
1104
|
+
}
|
|
1105
|
+
if (options?.metadata) {
|
|
1106
|
+
formData.append("metadata", JSON.stringify(options.metadata));
|
|
1107
|
+
}
|
|
1108
|
+
const response = await req.post({
|
|
1109
|
+
url: uploadUrl,
|
|
1110
|
+
data: formData,
|
|
1111
|
+
signal: options?.signal
|
|
1112
|
+
});
|
|
1113
|
+
return {
|
|
1114
|
+
url: response.data.publicUrl
|
|
1115
|
+
};
|
|
1116
|
+
},
|
|
1117
|
+
/**
|
|
1118
|
+
* 上传图片(快捷方法,专为 AI 设计)
|
|
1119
|
+
*
|
|
1120
|
+
* @example
|
|
1121
|
+
* ```typescript
|
|
1122
|
+
* const { url } = await client.upload.image(imageFile)
|
|
1123
|
+
* ```
|
|
1124
|
+
*/
|
|
1125
|
+
async image(file) {
|
|
1126
|
+
const result = await this.file(file);
|
|
1127
|
+
return { url: result.url };
|
|
1128
|
+
},
|
|
1129
|
+
/**
|
|
1130
|
+
* 批量上传文件
|
|
1131
|
+
*
|
|
1132
|
+
* @example
|
|
1133
|
+
* ```typescript
|
|
1134
|
+
* const result = await client.upload.batch({
|
|
1135
|
+
* files: [file1, file2, file3],
|
|
1136
|
+
* concurrent: 3,
|
|
1137
|
+
* onProgress: (completed, total) => {
|
|
1138
|
+
* console.log(`${completed}/${total}`)
|
|
1139
|
+
* }
|
|
1140
|
+
* })
|
|
1141
|
+
* ```
|
|
1142
|
+
*/
|
|
1143
|
+
async batch(options) {
|
|
1144
|
+
const { files, concurrent = 3, onProgress, onFileComplete, signal } = options;
|
|
1145
|
+
const success = [];
|
|
1146
|
+
const failed = [];
|
|
1147
|
+
let completed = 0;
|
|
1148
|
+
for (let i = 0; i < files.length; i += concurrent) {
|
|
1149
|
+
if (signal?.aborted) break;
|
|
1150
|
+
const batch = files.slice(i, Math.min(i + concurrent, files.length));
|
|
1151
|
+
const promises = batch.map(async (file, batchIndex) => {
|
|
1152
|
+
const globalIndex = i + batchIndex;
|
|
1153
|
+
try {
|
|
1154
|
+
const result = await this.file(file, { signal });
|
|
1155
|
+
success.push(result);
|
|
1156
|
+
if (onFileComplete) {
|
|
1157
|
+
onFileComplete(result, globalIndex);
|
|
1158
|
+
}
|
|
1159
|
+
} catch (error) {
|
|
1160
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
1161
|
+
failed.push({ index: globalIndex, error: errorMsg });
|
|
1162
|
+
if (onFileComplete) {
|
|
1163
|
+
onFileComplete(
|
|
1164
|
+
error instanceof Error ? error : new Error(errorMsg),
|
|
1165
|
+
globalIndex
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
} finally {
|
|
1169
|
+
completed++;
|
|
1170
|
+
if (onProgress) {
|
|
1171
|
+
onProgress(completed, files.length);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
});
|
|
1175
|
+
await Promise.all(promises);
|
|
1176
|
+
}
|
|
1177
|
+
return {
|
|
1178
|
+
success,
|
|
1179
|
+
failed,
|
|
1180
|
+
total: files.length
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// src/components/auth/LoginForm.tsx
|
|
1187
|
+
var import_react2 = require("react");
|
|
1188
|
+
var import_react3 = require("@iconify/react");
|
|
1189
|
+
var import_lucide_react = require("lucide-react");
|
|
1190
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1191
|
+
var LoginForm = ({
|
|
1192
|
+
onLoginSuccess,
|
|
1193
|
+
appName = "AI Application Platform",
|
|
1194
|
+
className = ""
|
|
1195
|
+
}) => {
|
|
1196
|
+
const [email, setEmail] = (0, import_react2.useState)("");
|
|
1197
|
+
const [code, setCode] = (0, import_react2.useState)("");
|
|
1198
|
+
const [validationErrors, setValidationErrors] = (0, import_react2.useState)({});
|
|
1199
|
+
const [isAnyLoading, setIsAnyLoading] = (0, import_react2.useState)(false);
|
|
1200
|
+
const [codeSent, setCodeSent] = (0, import_react2.useState)(false);
|
|
1201
|
+
const [loginError, setLoginError] = (0, import_react2.useState)(null);
|
|
1202
|
+
const googleLogin = async () => {
|
|
1203
|
+
};
|
|
1204
|
+
const githubLogin = async () => {
|
|
1205
|
+
};
|
|
1206
|
+
const sendEmailCode = async (email2) => {
|
|
1207
|
+
setCodeSent(true);
|
|
1208
|
+
};
|
|
1209
|
+
const loginWithEmail = async (email2, code2) => {
|
|
1210
|
+
if (onLoginSuccess) onLoginSuccess();
|
|
1211
|
+
};
|
|
1212
|
+
const clearError = () => {
|
|
1213
|
+
setLoginError(null);
|
|
1214
|
+
setValidationErrors({});
|
|
1215
|
+
};
|
|
1216
|
+
(0, import_react2.useEffect)(() => {
|
|
1217
|
+
if (loginError) {
|
|
1218
|
+
try {
|
|
1219
|
+
const errorObj = JSON.parse(loginError);
|
|
1220
|
+
const newErrors = {};
|
|
1221
|
+
if (errorObj.code === 429) {
|
|
1222
|
+
newErrors.form = errorObj.msg || "\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5";
|
|
1223
|
+
} else if (errorObj.data?.code === 401 && errorObj.data?.message) {
|
|
1224
|
+
if (codeSent) {
|
|
1225
|
+
newErrors.code = errorObj.data.message;
|
|
1226
|
+
} else {
|
|
1227
|
+
newErrors.form = errorObj.data.message;
|
|
1228
|
+
}
|
|
1229
|
+
} else if (errorObj.msg) {
|
|
1230
|
+
newErrors.form = errorObj.msg;
|
|
1231
|
+
} else if (errorObj.data?.message) {
|
|
1232
|
+
newErrors.form = errorObj.data.message;
|
|
1233
|
+
} else {
|
|
1234
|
+
newErrors.form = "\u53D1\u751F\u672A\u77E5\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5";
|
|
1235
|
+
}
|
|
1236
|
+
setValidationErrors(newErrors);
|
|
1237
|
+
} catch (e) {
|
|
1238
|
+
setValidationErrors({ form: loginError });
|
|
1239
|
+
}
|
|
1240
|
+
const timer = setTimeout(() => {
|
|
1241
|
+
clearError();
|
|
1242
|
+
}, 8e3);
|
|
1243
|
+
return () => clearTimeout(timer);
|
|
1244
|
+
}
|
|
1245
|
+
}, [loginError, codeSent]);
|
|
1246
|
+
const handleSubmit = async (e) => {
|
|
1247
|
+
e.preventDefault();
|
|
1248
|
+
const formData = new FormData(e.currentTarget);
|
|
1249
|
+
setValidationErrors({});
|
|
1250
|
+
if (!codeSent) {
|
|
1251
|
+
const emailValue = formData.get("email");
|
|
1252
|
+
if (!emailValue) {
|
|
1253
|
+
setValidationErrors({ email: "Please enter your email address" });
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
setIsAnyLoading(true);
|
|
1257
|
+
try {
|
|
1258
|
+
await sendEmailCode(emailValue);
|
|
1259
|
+
setEmail(emailValue);
|
|
1260
|
+
} catch (error) {
|
|
1261
|
+
setLoginError(error instanceof Error ? error.message : "Failed to send code");
|
|
1262
|
+
} finally {
|
|
1263
|
+
setIsAnyLoading(false);
|
|
1264
|
+
}
|
|
1265
|
+
} else {
|
|
1266
|
+
const codeValue = code;
|
|
1267
|
+
if (!codeValue || codeValue.length !== 6) {
|
|
1268
|
+
setValidationErrors({ code: "Please enter the 6-digit verification code" });
|
|
1269
|
+
return;
|
|
1270
|
+
}
|
|
1271
|
+
setIsAnyLoading(true);
|
|
1272
|
+
try {
|
|
1273
|
+
await loginWithEmail(email, codeValue);
|
|
1274
|
+
} catch (error) {
|
|
1275
|
+
setLoginError(error instanceof Error ? error.message : "Login failed");
|
|
1276
|
+
} finally {
|
|
1277
|
+
setIsAnyLoading(false);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
};
|
|
1281
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `w-full space-y-6 ${className}`, children: [
|
|
1282
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-1", children: [
|
|
1283
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { className: "text-3xl font-bold text-gray-900", children: "Welcome Back!" }),
|
|
1284
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-gray-600", children: "Please enter log in details below" })
|
|
1285
|
+
] }),
|
|
1286
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { className: "space-y-5", onSubmit: handleSubmit, children: [
|
|
1287
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-2", children: [
|
|
1288
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { htmlFor: "email", className: "text-gray-700 font-medium text-sm block", children: "Email" }),
|
|
1289
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1290
|
+
"input",
|
|
1291
|
+
{
|
|
1292
|
+
id: "email",
|
|
1293
|
+
type: "email",
|
|
1294
|
+
name: "email",
|
|
1295
|
+
value: email,
|
|
1296
|
+
onChange: (e) => {
|
|
1297
|
+
const value = e.target.value;
|
|
1298
|
+
setEmail(value);
|
|
1299
|
+
if (validationErrors.email) {
|
|
1300
|
+
const newErrors = { ...validationErrors };
|
|
1301
|
+
delete newErrors.email;
|
|
1302
|
+
setValidationErrors(newErrors);
|
|
1303
|
+
}
|
|
1304
|
+
},
|
|
1305
|
+
required: true,
|
|
1306
|
+
"aria-invalid": !!validationErrors.email,
|
|
1307
|
+
className: "w-full text-sm bg-gray-50 rounded-md h-11 px-3 hover:bg-gray-100 focus:bg-white border border-gray-200 focus:border-gray-400 focus:outline-none",
|
|
1308
|
+
placeholder: ""
|
|
1309
|
+
}
|
|
1310
|
+
),
|
|
1311
|
+
validationErrors.email && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-red-600 text-sm", children: validationErrors.email })
|
|
1312
|
+
] }),
|
|
1313
|
+
codeSent && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-2", children: [
|
|
1314
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "text-gray-700 font-medium text-sm block", children: "Verification Code" }),
|
|
1315
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1316
|
+
"input",
|
|
1317
|
+
{
|
|
1318
|
+
type: "text",
|
|
1319
|
+
maxLength: 6,
|
|
1320
|
+
value: code,
|
|
1321
|
+
onChange: (e) => {
|
|
1322
|
+
const value = e.target.value.replace(/\D/g, "");
|
|
1323
|
+
setCode(value);
|
|
1324
|
+
if (validationErrors.code) {
|
|
1325
|
+
const newErrors = { ...validationErrors };
|
|
1326
|
+
delete newErrors.code;
|
|
1327
|
+
setValidationErrors(newErrors);
|
|
1328
|
+
}
|
|
1329
|
+
},
|
|
1330
|
+
"aria-invalid": !!validationErrors.code,
|
|
1331
|
+
className: "w-full text-center text-sm bg-gray-50 rounded-md h-11 px-3 hover:bg-gray-100 focus:bg-white border border-gray-200 focus:border-gray-400 focus:outline-none tracking-widest",
|
|
1332
|
+
placeholder: "000000"
|
|
1333
|
+
}
|
|
1334
|
+
),
|
|
1335
|
+
validationErrors.code && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-red-600 text-sm", children: validationErrors.code })
|
|
1336
|
+
] }),
|
|
1337
|
+
validationErrors.form && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-red-600 text-sm p-3 bg-red-50 rounded-md border border-red-200", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center", children: [
|
|
1338
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react3.Icon, { icon: "material-symbols:error", className: "text-red-600 mr-2" }),
|
|
1339
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: validationErrors.form })
|
|
1340
|
+
] }) }),
|
|
1341
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
977
1342
|
"button",
|
|
978
1343
|
{
|
|
979
1344
|
type: "submit",
|
|
@@ -1031,7 +1396,7 @@ var LoginForm = ({
|
|
|
1031
1396
|
};
|
|
1032
1397
|
|
|
1033
1398
|
// src/components/auth/HowoneProvider.tsx
|
|
1034
|
-
var
|
|
1399
|
+
var import_react8 = require("react");
|
|
1035
1400
|
init_auth();
|
|
1036
1401
|
|
|
1037
1402
|
// src/components/theme/ThemeProvider.tsx
|
|
@@ -1088,68 +1453,33 @@ var useTheme = () => {
|
|
|
1088
1453
|
};
|
|
1089
1454
|
|
|
1090
1455
|
// src/components/ui/Toast/GlobalToastContainer.tsx
|
|
1091
|
-
var
|
|
1092
|
-
var import_styles = require("goey-toast/styles.css");
|
|
1093
|
-
|
|
1094
|
-
// src/components/theme/ThemeToggle.tsx
|
|
1095
|
-
var React2 = __toESM(require("react"));
|
|
1096
|
-
var import_react5 = require("@iconify/react");
|
|
1456
|
+
var import_react_toastify = require("react-toastify");
|
|
1097
1457
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1098
|
-
function ThemeToggle({ className }) {
|
|
1099
|
-
const { setTheme, theme } = useTheme();
|
|
1100
|
-
const [mounted, setMounted] = React2.useState(false);
|
|
1101
|
-
React2.useEffect(() => {
|
|
1102
|
-
setMounted(true);
|
|
1103
|
-
}, []);
|
|
1104
|
-
const handleToggle = () => {
|
|
1105
|
-
if (theme === "dark") {
|
|
1106
|
-
setTheme("light");
|
|
1107
|
-
} else {
|
|
1108
|
-
setTheme("dark");
|
|
1109
|
-
}
|
|
1110
|
-
};
|
|
1111
|
-
if (!mounted) {
|
|
1112
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react5.Icon, { icon: "solar:sun-bold", width: 20, height: 20 });
|
|
1113
|
-
}
|
|
1114
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1115
|
-
"div",
|
|
1116
|
-
{
|
|
1117
|
-
className: `cursor-pointer ${className || ""}`,
|
|
1118
|
-
onClick: handleToggle,
|
|
1119
|
-
children: theme === "light" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react5.Icon, { icon: "solar:sun-bold", width: 20, height: 20 }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react5.Icon, { icon: "solar:moon-linear", width: 20, height: 20 })
|
|
1120
|
-
}
|
|
1121
|
-
);
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
// src/components/ui/Toast/GlobalToastContainer.tsx
|
|
1125
|
-
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1126
1458
|
function GlobalToastContainer() {
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1130
|
-
import_goey_toast.GoeyToaster,
|
|
1459
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1460
|
+
import_react_toastify.ToastContainer,
|
|
1131
1461
|
{
|
|
1132
|
-
|
|
1133
|
-
|
|
1462
|
+
newestOnTop: false,
|
|
1463
|
+
closeButton: false
|
|
1134
1464
|
}
|
|
1135
1465
|
);
|
|
1136
1466
|
}
|
|
1137
1467
|
|
|
1138
1468
|
// src/components/ElementSelectorProvider.tsx
|
|
1139
|
-
var
|
|
1469
|
+
var import_react7 = require("react");
|
|
1140
1470
|
|
|
1141
1471
|
// src/components/ElementSelector.tsx
|
|
1142
|
-
var
|
|
1143
|
-
var
|
|
1472
|
+
var import_react5 = require("react");
|
|
1473
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1144
1474
|
var ElementSelector = ({
|
|
1145
1475
|
active,
|
|
1146
1476
|
onSelect,
|
|
1147
1477
|
onCancel
|
|
1148
1478
|
}) => {
|
|
1149
|
-
const [hoveredElement, setHoveredElement] = (0,
|
|
1150
|
-
const [highlightRect, setHighlightRect] = (0,
|
|
1151
|
-
const overlayRef = (0,
|
|
1152
|
-
const getSourceLocation = (0,
|
|
1479
|
+
const [hoveredElement, setHoveredElement] = (0, import_react5.useState)(null);
|
|
1480
|
+
const [highlightRect, setHighlightRect] = (0, import_react5.useState)(null);
|
|
1481
|
+
const overlayRef = (0, import_react5.useRef)(null);
|
|
1482
|
+
const getSourceLocation = (0, import_react5.useCallback)((element) => {
|
|
1153
1483
|
let current = element;
|
|
1154
1484
|
while (current && current !== document.body) {
|
|
1155
1485
|
const sourceLocationAttr = current.getAttribute("data-source-location");
|
|
@@ -1164,7 +1494,7 @@ var ElementSelector = ({
|
|
|
1164
1494
|
}
|
|
1165
1495
|
return null;
|
|
1166
1496
|
}, []);
|
|
1167
|
-
const handleMouseMove = (0,
|
|
1497
|
+
const handleMouseMove = (0, import_react5.useCallback)((e) => {
|
|
1168
1498
|
if (!active) return;
|
|
1169
1499
|
const elements = document.elementsFromPoint(e.clientX, e.clientY);
|
|
1170
1500
|
const targetElement = elements.find(
|
|
@@ -1176,7 +1506,7 @@ var ElementSelector = ({
|
|
|
1176
1506
|
setHighlightRect(rect);
|
|
1177
1507
|
}
|
|
1178
1508
|
}, [active, hoveredElement]);
|
|
1179
|
-
const handleClick = (0,
|
|
1509
|
+
const handleClick = (0, import_react5.useCallback)((e) => {
|
|
1180
1510
|
if (!active || !hoveredElement) return;
|
|
1181
1511
|
e.preventDefault();
|
|
1182
1512
|
e.stopPropagation();
|
|
@@ -1204,7 +1534,7 @@ var ElementSelector = ({
|
|
|
1204
1534
|
}
|
|
1205
1535
|
}
|
|
1206
1536
|
}, [active, hoveredElement, getSourceLocation, onSelect, onCancel]);
|
|
1207
|
-
(0,
|
|
1537
|
+
(0, import_react5.useEffect)(() => {
|
|
1208
1538
|
if (active) {
|
|
1209
1539
|
document.addEventListener("mousemove", handleMouseMove);
|
|
1210
1540
|
document.addEventListener("click", handleClick, true);
|
|
@@ -1220,8 +1550,8 @@ var ElementSelector = ({
|
|
|
1220
1550
|
}
|
|
1221
1551
|
}, [active, handleMouseMove, handleClick]);
|
|
1222
1552
|
if (!active) return null;
|
|
1223
|
-
return /* @__PURE__ */ (0,
|
|
1224
|
-
/* @__PURE__ */ (0,
|
|
1553
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1554
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1225
1555
|
"div",
|
|
1226
1556
|
{
|
|
1227
1557
|
ref: overlayRef,
|
|
@@ -1238,7 +1568,7 @@ var ElementSelector = ({
|
|
|
1238
1568
|
}
|
|
1239
1569
|
}
|
|
1240
1570
|
),
|
|
1241
|
-
highlightRect && /* @__PURE__ */ (0,
|
|
1571
|
+
highlightRect && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1242
1572
|
"div",
|
|
1243
1573
|
{
|
|
1244
1574
|
style: {
|
|
@@ -1256,7 +1586,7 @@ var ElementSelector = ({
|
|
|
1256
1586
|
}
|
|
1257
1587
|
}
|
|
1258
1588
|
),
|
|
1259
|
-
hoveredElement && highlightRect && /* @__PURE__ */ (0,
|
|
1589
|
+
hoveredElement && highlightRect && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1260
1590
|
"div",
|
|
1261
1591
|
{
|
|
1262
1592
|
style: {
|
|
@@ -1282,17 +1612,17 @@ var ElementSelector = ({
|
|
|
1282
1612
|
};
|
|
1283
1613
|
|
|
1284
1614
|
// src/hooks/use-element-selector.ts
|
|
1285
|
-
var
|
|
1615
|
+
var import_react6 = require("react");
|
|
1286
1616
|
function useElementSelector() {
|
|
1287
|
-
const [isSelecting, setIsSelecting] = (0,
|
|
1288
|
-
const [selectedElement, setSelectedElement] = (0,
|
|
1289
|
-
const startSelecting = (0,
|
|
1617
|
+
const [isSelecting, setIsSelecting] = (0, import_react6.useState)(false);
|
|
1618
|
+
const [selectedElement, setSelectedElement] = (0, import_react6.useState)(null);
|
|
1619
|
+
const startSelecting = (0, import_react6.useCallback)(() => {
|
|
1290
1620
|
setIsSelecting(true);
|
|
1291
1621
|
}, []);
|
|
1292
|
-
const stopSelecting = (0,
|
|
1622
|
+
const stopSelecting = (0, import_react6.useCallback)(() => {
|
|
1293
1623
|
setIsSelecting(false);
|
|
1294
1624
|
}, []);
|
|
1295
|
-
const clearSelection = (0,
|
|
1625
|
+
const clearSelection = (0, import_react6.useCallback)(() => {
|
|
1296
1626
|
setSelectedElement(null);
|
|
1297
1627
|
}, []);
|
|
1298
1628
|
return {
|
|
@@ -1313,10 +1643,10 @@ function sendElementSelectionToParent(data) {
|
|
|
1313
1643
|
}
|
|
1314
1644
|
|
|
1315
1645
|
// src/components/ElementSelectorProvider.tsx
|
|
1316
|
-
var
|
|
1646
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1317
1647
|
var ElementSelectorProvider = ({ children }) => {
|
|
1318
|
-
const [isSelecting, setIsSelecting] = (0,
|
|
1319
|
-
const handleCancel = (0,
|
|
1648
|
+
const [isSelecting, setIsSelecting] = (0, import_react7.useState)(false);
|
|
1649
|
+
const handleCancel = (0, import_react7.useCallback)(() => {
|
|
1320
1650
|
setIsSelecting(false);
|
|
1321
1651
|
if (window.parent && window.parent !== window) {
|
|
1322
1652
|
window.parent.postMessage({
|
|
@@ -1324,10 +1654,10 @@ var ElementSelectorProvider = ({ children }) => {
|
|
|
1324
1654
|
}, "*");
|
|
1325
1655
|
}
|
|
1326
1656
|
}, []);
|
|
1327
|
-
const handleSelect = (0,
|
|
1657
|
+
const handleSelect = (0, import_react7.useCallback)((data) => {
|
|
1328
1658
|
sendElementSelectionToParent(data);
|
|
1329
1659
|
}, []);
|
|
1330
|
-
(0,
|
|
1660
|
+
(0, import_react7.useEffect)(() => {
|
|
1331
1661
|
const handleStartSelection = () => {
|
|
1332
1662
|
setIsSelecting(true);
|
|
1333
1663
|
};
|
|
@@ -1350,9 +1680,9 @@ var ElementSelectorProvider = ({ children }) => {
|
|
|
1350
1680
|
window.removeEventListener("message", handleMessage);
|
|
1351
1681
|
};
|
|
1352
1682
|
}, [handleCancel]);
|
|
1353
|
-
return /* @__PURE__ */ (0,
|
|
1683
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1354
1684
|
children,
|
|
1355
|
-
/* @__PURE__ */ (0,
|
|
1685
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1356
1686
|
ElementSelector,
|
|
1357
1687
|
{
|
|
1358
1688
|
active: isSelecting,
|
|
@@ -1365,8 +1695,8 @@ var ElementSelectorProvider = ({ children }) => {
|
|
|
1365
1695
|
|
|
1366
1696
|
// src/components/auth/HowoneProvider.tsx
|
|
1367
1697
|
init_config();
|
|
1368
|
-
var
|
|
1369
|
-
var HowoneContext = (0,
|
|
1698
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1699
|
+
var HowoneContext = (0, import_react8.createContext)(null);
|
|
1370
1700
|
var consumedTokenCache = /* @__PURE__ */ new Set();
|
|
1371
1701
|
var redirectOverlayStylesInjected = false;
|
|
1372
1702
|
var injectRedirectOverlayStyles = () => {
|
|
@@ -1427,15 +1757,15 @@ var HowOneProvider = ({
|
|
|
1427
1757
|
forceDefaultTheme = false,
|
|
1428
1758
|
redirectOnUnauthenticated = true
|
|
1429
1759
|
}) => {
|
|
1430
|
-
const [user, setUser] = (0,
|
|
1431
|
-
const [token, setTokenState] = (0,
|
|
1432
|
-
const [hasCheckedUrlToken, setHasCheckedUrlToken] = (0,
|
|
1433
|
-
const [pendingRedirect, setPendingRedirect] = (0,
|
|
1434
|
-
const authCookieRoot = (0,
|
|
1760
|
+
const [user, setUser] = (0, import_react8.useState)(() => parseUserFromToken(getToken()));
|
|
1761
|
+
const [token, setTokenState] = (0, import_react8.useState)(() => getToken());
|
|
1762
|
+
const [hasCheckedUrlToken, setHasCheckedUrlToken] = (0, import_react8.useState)(false);
|
|
1763
|
+
const [pendingRedirect, setPendingRedirect] = (0, import_react8.useState)(false);
|
|
1764
|
+
const authCookieRoot = (0, import_react8.useMemo)(() => {
|
|
1435
1765
|
const env3 = getGlobalEnvironment() ?? "dev";
|
|
1436
1766
|
return setEnvironment(env3).AUTH_COOKIE_ROOT_VALUE;
|
|
1437
1767
|
}, []);
|
|
1438
|
-
const consumeTokenToCookie = (0,
|
|
1768
|
+
const consumeTokenToCookie = (0, import_react8.useCallback)(async (value2) => {
|
|
1439
1769
|
if (!value2) return;
|
|
1440
1770
|
if (consumedTokenCache.has(value2)) return;
|
|
1441
1771
|
consumedTokenCache.add(value2);
|
|
@@ -1462,7 +1792,7 @@ var HowOneProvider = ({
|
|
|
1462
1792
|
console.warn("[HowOneProvider] Failed to consume token:", error);
|
|
1463
1793
|
}
|
|
1464
1794
|
}, [authCookieRoot]);
|
|
1465
|
-
const logoutFromCookie = (0,
|
|
1795
|
+
const logoutFromCookie = (0, import_react8.useCallback)(async () => {
|
|
1466
1796
|
try {
|
|
1467
1797
|
await fetch(`${authCookieRoot}/logout`, {
|
|
1468
1798
|
method: "POST",
|
|
@@ -1472,7 +1802,7 @@ var HowOneProvider = ({
|
|
|
1472
1802
|
console.warn("[HowOneProvider] Failed to logout from cookie:", error);
|
|
1473
1803
|
}
|
|
1474
1804
|
}, [authCookieRoot]);
|
|
1475
|
-
const readAccessTokenCookie = (0,
|
|
1805
|
+
const readAccessTokenCookie = (0, import_react8.useCallback)(() => {
|
|
1476
1806
|
if (typeof document === "undefined") return null;
|
|
1477
1807
|
try {
|
|
1478
1808
|
const parts = document.cookie.split("; ");
|
|
@@ -1488,7 +1818,7 @@ var HowOneProvider = ({
|
|
|
1488
1818
|
}
|
|
1489
1819
|
return null;
|
|
1490
1820
|
}, []);
|
|
1491
|
-
(0,
|
|
1821
|
+
(0, import_react8.useEffect)(() => {
|
|
1492
1822
|
try {
|
|
1493
1823
|
const params = new URLSearchParams(window.location.search);
|
|
1494
1824
|
let urlToken = params.get("access_token") || params.get("token");
|
|
@@ -1522,7 +1852,7 @@ var HowOneProvider = ({
|
|
|
1522
1852
|
setHasCheckedUrlToken(true);
|
|
1523
1853
|
}
|
|
1524
1854
|
}, [consumeTokenToCookie, readAccessTokenCookie]);
|
|
1525
|
-
const resolvedAuthUrl = (0,
|
|
1855
|
+
const resolvedAuthUrl = (0, import_react8.useMemo)(() => {
|
|
1526
1856
|
const env3 = getGlobalEnvironment() ?? "dev";
|
|
1527
1857
|
switch (env3) {
|
|
1528
1858
|
case "local":
|
|
@@ -1534,12 +1864,12 @@ var HowOneProvider = ({
|
|
|
1534
1864
|
return "https://howone.dev/auth";
|
|
1535
1865
|
}
|
|
1536
1866
|
}, []);
|
|
1537
|
-
(0,
|
|
1867
|
+
(0, import_react8.useEffect)(() => {
|
|
1538
1868
|
if (pendingRedirect) {
|
|
1539
1869
|
injectRedirectOverlayStyles();
|
|
1540
1870
|
}
|
|
1541
1871
|
}, [pendingRedirect]);
|
|
1542
|
-
const redirectToAuth = (0,
|
|
1872
|
+
const redirectToAuth = (0, import_react8.useCallback)(() => {
|
|
1543
1873
|
if (!redirectOnUnauthenticated || typeof window === "undefined") return;
|
|
1544
1874
|
const activeProjectId = projectId ?? getDefaultProjectId();
|
|
1545
1875
|
const navigateToResolvedAuth = () => {
|
|
@@ -1581,7 +1911,7 @@ var HowOneProvider = ({
|
|
|
1581
1911
|
navigateToResolvedAuth();
|
|
1582
1912
|
}
|
|
1583
1913
|
}, [redirectOnUnauthenticated, resolvedAuthUrl, projectId]);
|
|
1584
|
-
(0,
|
|
1914
|
+
(0, import_react8.useEffect)(() => {
|
|
1585
1915
|
if (!hasCheckedUrlToken) return;
|
|
1586
1916
|
if (!token && !user) {
|
|
1587
1917
|
redirectToAuth();
|
|
@@ -1604,31 +1934,31 @@ var HowOneProvider = ({
|
|
|
1604
1934
|
logout
|
|
1605
1935
|
};
|
|
1606
1936
|
if (!hasCheckedUrlToken) return null;
|
|
1607
|
-
return /* @__PURE__ */ (0,
|
|
1937
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1608
1938
|
ThemeProvider,
|
|
1609
1939
|
{
|
|
1610
1940
|
defaultTheme,
|
|
1611
1941
|
storageKey: themeStorageKey,
|
|
1612
1942
|
forceDefault: forceDefaultTheme,
|
|
1613
1943
|
children: [
|
|
1614
|
-
/* @__PURE__ */ (0,
|
|
1944
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ElementSelectorProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(HowoneContext.Provider, { value, children: [
|
|
1615
1945
|
children,
|
|
1616
|
-
showHowOneFlag && /* @__PURE__ */ (0,
|
|
1617
|
-
pendingRedirect && /* @__PURE__ */ (0,
|
|
1946
|
+
showHowOneFlag && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloatingButton, { onClick: () => window.open("https://howone.ai", "_blank") }),
|
|
1947
|
+
pendingRedirect && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1618
1948
|
"div",
|
|
1619
1949
|
{
|
|
1620
1950
|
"data-howone-auth-overlay-root": true,
|
|
1621
1951
|
className: "fixed inset-0 z-[100000] h-full w-full flex flex-col items-center justify-center bg-black/65 backdrop-blur-sm text-white",
|
|
1622
|
-
children: /* @__PURE__ */ (0,
|
|
1623
|
-
/* @__PURE__ */ (0,
|
|
1952
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "relative mt-6 flex h-[220px] w-[220px] items-center justify-center", children: [
|
|
1953
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1624
1954
|
"div",
|
|
1625
1955
|
{
|
|
1626
1956
|
className: "absolute inset-0 rounded-full bg-white/20",
|
|
1627
1957
|
style: { animation: "howone-glow-ring 2.4s ease-in-out infinite" }
|
|
1628
1958
|
}
|
|
1629
1959
|
),
|
|
1630
|
-
/* @__PURE__ */ (0,
|
|
1631
|
-
/* @__PURE__ */ (0,
|
|
1960
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "absolute inset-0 rounded-full bg-gradient-to-br from-white/10 via-white/25 to-white/10 blur-2xl" }),
|
|
1961
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1632
1962
|
"img",
|
|
1633
1963
|
{
|
|
1634
1964
|
style: { width: 250, animation: "howone-logo-pulse 2s ease-in-out infinite" },
|
|
@@ -1640,13 +1970,13 @@ var HowOneProvider = ({
|
|
|
1640
1970
|
}
|
|
1641
1971
|
)
|
|
1642
1972
|
] }) }),
|
|
1643
|
-
/* @__PURE__ */ (0,
|
|
1973
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(GlobalToastContainer, {})
|
|
1644
1974
|
]
|
|
1645
1975
|
}
|
|
1646
1976
|
);
|
|
1647
1977
|
};
|
|
1648
1978
|
function useHowoneContext() {
|
|
1649
|
-
const ctx = (0,
|
|
1979
|
+
const ctx = (0, import_react8.useContext)(HowoneContext);
|
|
1650
1980
|
if (!ctx) {
|
|
1651
1981
|
const t = getToken();
|
|
1652
1982
|
return {
|
|
@@ -1750,7 +2080,7 @@ var howone = {
|
|
|
1750
2080
|
var client_default = howone;
|
|
1751
2081
|
|
|
1752
2082
|
// src/components/ui/Loading.tsx
|
|
1753
|
-
var
|
|
2083
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1754
2084
|
var Loading = ({
|
|
1755
2085
|
size = "md",
|
|
1756
2086
|
text = "Loading...",
|
|
@@ -1763,14 +2093,14 @@ var Loading = ({
|
|
|
1763
2093
|
lg: "h-12 w-12"
|
|
1764
2094
|
};
|
|
1765
2095
|
const containerClasses = fullScreen ? "fixed inset-0 flex items-center justify-center bg-white/80 backdrop-blur-sm z-50" : "flex items-center justify-center p-4";
|
|
1766
|
-
return /* @__PURE__ */ (0,
|
|
1767
|
-
/* @__PURE__ */ (0,
|
|
2096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: `${containerClasses} ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "text-center", children: [
|
|
2097
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1768
2098
|
"div",
|
|
1769
2099
|
{
|
|
1770
2100
|
className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 mx-auto ${sizeClasses[size]}`
|
|
1771
2101
|
}
|
|
1772
2102
|
),
|
|
1773
|
-
text && /* @__PURE__ */ (0,
|
|
2103
|
+
text && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "mt-2 text-sm text-gray-600", children: text })
|
|
1774
2104
|
] }) });
|
|
1775
2105
|
};
|
|
1776
2106
|
var LoadingSpinner = ({
|
|
@@ -1782,7 +2112,7 @@ var LoadingSpinner = ({
|
|
|
1782
2112
|
md: "h-8 w-8",
|
|
1783
2113
|
lg: "h-12 w-12"
|
|
1784
2114
|
};
|
|
1785
|
-
return /* @__PURE__ */ (0,
|
|
2115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1786
2116
|
"div",
|
|
1787
2117
|
{
|
|
1788
2118
|
className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 ${sizeClasses[size]} ${className}`
|
|
@@ -1791,9 +2121,9 @@ var LoadingSpinner = ({
|
|
|
1791
2121
|
};
|
|
1792
2122
|
|
|
1793
2123
|
// src/components/ui/ErrorBoundary.tsx
|
|
1794
|
-
var
|
|
1795
|
-
var
|
|
1796
|
-
var ErrorBoundary = class extends
|
|
2124
|
+
var import_react9 = require("react");
|
|
2125
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
2126
|
+
var ErrorBoundary = class extends import_react9.Component {
|
|
1797
2127
|
constructor(props) {
|
|
1798
2128
|
super(props);
|
|
1799
2129
|
this.handleRetry = () => {
|
|
@@ -1815,13 +2145,13 @@ var ErrorBoundary = class extends import_react10.Component {
|
|
|
1815
2145
|
if (this.state.hasError) {
|
|
1816
2146
|
if (this.props.fallback) {
|
|
1817
2147
|
const FallbackComponent = this.props.fallback;
|
|
1818
|
-
return /* @__PURE__ */ (0,
|
|
2148
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(FallbackComponent, { error: this.state.error, retry: this.handleRetry });
|
|
1819
2149
|
}
|
|
1820
|
-
return /* @__PURE__ */ (0,
|
|
1821
|
-
/* @__PURE__ */ (0,
|
|
1822
|
-
/* @__PURE__ */ (0,
|
|
1823
|
-
/* @__PURE__ */ (0,
|
|
1824
|
-
/* @__PURE__ */ (0,
|
|
2150
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "min-h-[400px] flex items-center justify-center p-4", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "text-center max-w-md", children: [
|
|
2151
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "text-red-500 text-6xl mb-4", children: "\u26A0\uFE0F" }),
|
|
2152
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h2", { className: "text-xl font-semibold text-gray-900 mb-2", children: "Something went wrong" }),
|
|
2153
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-gray-600 mb-4", children: "An unexpected error occurred. Please try refreshing the page." }),
|
|
2154
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1825
2155
|
"button",
|
|
1826
2156
|
{
|
|
1827
2157
|
onClick: this.handleRetry,
|
|
@@ -1835,10 +2165,10 @@ var ErrorBoundary = class extends import_react10.Component {
|
|
|
1835
2165
|
return this.props.children;
|
|
1836
2166
|
}
|
|
1837
2167
|
};
|
|
1838
|
-
var DefaultErrorFallback = ({ retry }) => /* @__PURE__ */ (0,
|
|
1839
|
-
/* @__PURE__ */ (0,
|
|
1840
|
-
/* @__PURE__ */ (0,
|
|
1841
|
-
retry && /* @__PURE__ */ (0,
|
|
2168
|
+
var DefaultErrorFallback = ({ retry }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "min-h-[200px] flex items-center justify-center p-4", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "text-center", children: [
|
|
2169
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "text-red-500 text-4xl mb-2", children: "\u26A0\uFE0F" }),
|
|
2170
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-gray-600 mb-2", children: "Something went wrong" }),
|
|
2171
|
+
retry && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1842
2172
|
"button",
|
|
1843
2173
|
{
|
|
1844
2174
|
onClick: retry,
|
|
@@ -1849,7 +2179,7 @@ var DefaultErrorFallback = ({ retry }) => /* @__PURE__ */ (0, import_jsx_runtime
|
|
|
1849
2179
|
] }) });
|
|
1850
2180
|
|
|
1851
2181
|
// src/components/ui/ClayxButton.tsx
|
|
1852
|
-
var
|
|
2182
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1853
2183
|
var getSizeClasses = (size, isIconOnly) => {
|
|
1854
2184
|
if (isIconOnly) {
|
|
1855
2185
|
switch (size) {
|
|
@@ -1905,7 +2235,7 @@ var ClayxButton = ({
|
|
|
1905
2235
|
disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none
|
|
1906
2236
|
`.replace(/\s+/g, " ").trim();
|
|
1907
2237
|
const combinedClasses = `${baseClasses} ${sizeClasses} ${variantClasses} ${className}`.trim();
|
|
1908
|
-
return /* @__PURE__ */ (0,
|
|
2238
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1909
2239
|
"button",
|
|
1910
2240
|
{
|
|
1911
2241
|
className: combinedClasses,
|
|
@@ -1917,57 +2247,204 @@ var ClayxButton = ({
|
|
|
1917
2247
|
};
|
|
1918
2248
|
|
|
1919
2249
|
// src/components/ui/LimitUpgradeToast.tsx
|
|
2250
|
+
var import_react13 = __toESM(require("react"));
|
|
2251
|
+
var import_react14 = require("@iconify/react");
|
|
2252
|
+
|
|
2253
|
+
// src/components/ui/Toast/ClayxToast.tsx
|
|
1920
2254
|
var import_react11 = __toESM(require("react"));
|
|
2255
|
+
var import_react_toastify2 = require("react-toastify");
|
|
1921
2256
|
var import_react12 = require("@iconify/react");
|
|
1922
2257
|
|
|
1923
|
-
// src/components/
|
|
1924
|
-
var
|
|
1925
|
-
var
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
...rawOptions,
|
|
1939
|
-
id,
|
|
1940
|
-
description,
|
|
1941
|
-
...duration !== void 0 ? { duration } : {}
|
|
1942
|
-
};
|
|
1943
|
-
const title = params.title ?? "";
|
|
1944
|
-
if (type === "default") {
|
|
1945
|
-
(0, import_goey_toast2.goeyToast)(title, goeyOptions);
|
|
1946
|
-
return;
|
|
2258
|
+
// src/components/theme/ThemeToggle.tsx
|
|
2259
|
+
var React6 = __toESM(require("react"));
|
|
2260
|
+
var import_react10 = require("@iconify/react");
|
|
2261
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2262
|
+
function ThemeToggle({ className }) {
|
|
2263
|
+
const { setTheme, theme } = useTheme();
|
|
2264
|
+
const [mounted, setMounted] = React6.useState(false);
|
|
2265
|
+
React6.useEffect(() => {
|
|
2266
|
+
setMounted(true);
|
|
2267
|
+
}, []);
|
|
2268
|
+
const handleToggle = () => {
|
|
2269
|
+
if (theme === "dark") {
|
|
2270
|
+
setTheme("light");
|
|
2271
|
+
} else {
|
|
2272
|
+
setTheme("dark");
|
|
1947
2273
|
}
|
|
1948
|
-
import_goey_toast2.goeyToast[type](title, goeyOptions);
|
|
1949
2274
|
};
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
2275
|
+
if (!mounted) {
|
|
2276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react10.Icon, { icon: "solar:sun-bold", width: 20, height: 20 });
|
|
2277
|
+
}
|
|
2278
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2279
|
+
"div",
|
|
2280
|
+
{
|
|
2281
|
+
className: `cursor-pointer ${className || ""}`,
|
|
2282
|
+
onClick: handleToggle,
|
|
2283
|
+
children: theme === "light" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react10.Icon, { icon: "solar:sun-bold", width: 20, height: 20 }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react10.Icon, { icon: "solar:moon-linear", width: 20, height: 20 })
|
|
2284
|
+
}
|
|
2285
|
+
);
|
|
2286
|
+
}
|
|
1958
2287
|
|
|
1959
|
-
// src/components/ui/
|
|
2288
|
+
// src/components/ui/Toast/ClayxToast.tsx
|
|
1960
2289
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1961
|
-
var
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
2290
|
+
var TOAST_ICONS = {
|
|
2291
|
+
success: {
|
|
2292
|
+
icon: "mdi:success",
|
|
2293
|
+
color: "text-green-400",
|
|
2294
|
+
className: "text-green-400",
|
|
2295
|
+
dark: {
|
|
2296
|
+
bgGradient: "bg-[#14181d]",
|
|
2297
|
+
gradientColor: "#389726",
|
|
2298
|
+
borderGradient: "border-[#389726]",
|
|
2299
|
+
borderGradientColor: "#389726"
|
|
2300
|
+
},
|
|
2301
|
+
light: {
|
|
2302
|
+
bgGradient: "bg-[#fafafa]",
|
|
2303
|
+
gradientColor: "#22c55e",
|
|
2304
|
+
borderGradient: "border-[#22c55e]",
|
|
2305
|
+
borderGradientColor: "#22c55e"
|
|
2306
|
+
}
|
|
2307
|
+
},
|
|
2308
|
+
error: {
|
|
2309
|
+
icon: "ic:outline-close",
|
|
2310
|
+
color: "text-red-400",
|
|
2311
|
+
className: "text-red-400",
|
|
2312
|
+
dark: {
|
|
2313
|
+
bgGradient: "bg-[#14181d]",
|
|
2314
|
+
gradientColor: "#ef4444",
|
|
2315
|
+
borderGradient: "border-[#ef4444]",
|
|
2316
|
+
borderGradientColor: "#ef4444"
|
|
2317
|
+
},
|
|
2318
|
+
light: {
|
|
2319
|
+
bgGradient: "bg-[#fafafa]",
|
|
2320
|
+
gradientColor: "#f87171",
|
|
2321
|
+
borderGradient: "border-[#f87171]",
|
|
2322
|
+
borderGradientColor: "#f87171"
|
|
2323
|
+
}
|
|
2324
|
+
},
|
|
2325
|
+
warning: {
|
|
2326
|
+
icon: "mi:warning",
|
|
2327
|
+
color: "text-yellow-400",
|
|
2328
|
+
className: "text-yellow-400",
|
|
2329
|
+
dark: {
|
|
2330
|
+
bgGradient: "bg-[#14181d]",
|
|
2331
|
+
gradientColor: "#facc15",
|
|
2332
|
+
borderGradient: "border-[#facc15]",
|
|
2333
|
+
borderGradientColor: "#facc15"
|
|
2334
|
+
},
|
|
2335
|
+
light: {
|
|
2336
|
+
bgGradient: "bg-[#fafafa]",
|
|
2337
|
+
gradientColor: "#f59e0b",
|
|
2338
|
+
borderGradient: "border-[#f59e0b]",
|
|
2339
|
+
borderGradientColor: "#f59e0b"
|
|
2340
|
+
}
|
|
2341
|
+
},
|
|
2342
|
+
info: {
|
|
2343
|
+
icon: "ic:outline-info",
|
|
2344
|
+
color: "text-blue-400",
|
|
2345
|
+
className: "text-blue-400",
|
|
2346
|
+
dark: {
|
|
2347
|
+
bgGradient: "bg-[#14181d]",
|
|
2348
|
+
gradientColor: "#60a5fa",
|
|
2349
|
+
borderGradient: "border-[#60a5fa]",
|
|
2350
|
+
borderGradientColor: "#f0f0f0"
|
|
2351
|
+
},
|
|
2352
|
+
light: {
|
|
2353
|
+
bgGradient: "bg-[#fafafa]",
|
|
2354
|
+
gradientColor: "#3b82f6",
|
|
2355
|
+
borderGradient: "border-[#3b82f6]",
|
|
2356
|
+
borderGradientColor: "#3b82f6"
|
|
2357
|
+
}
|
|
2358
|
+
},
|
|
2359
|
+
default: {
|
|
2360
|
+
icon: "ic:round-notifications",
|
|
2361
|
+
color: "text-gray-400",
|
|
2362
|
+
className: "text-gray-400",
|
|
2363
|
+
dark: {
|
|
2364
|
+
bgGradient: "bg-[#14181d]",
|
|
2365
|
+
gradientColor: "#9ca3af",
|
|
2366
|
+
borderGradient: "border-[#9ca3af]",
|
|
2367
|
+
borderGradientColor: "#9ca3af"
|
|
2368
|
+
},
|
|
2369
|
+
light: {
|
|
2370
|
+
bgGradient: "bg-[#fafafa]",
|
|
2371
|
+
gradientColor: "#6b7280",
|
|
2372
|
+
borderGradient: "border-[#6b7280]",
|
|
2373
|
+
borderGradientColor: "#6b7280"
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
};
|
|
2377
|
+
var CloseButton = import_react11.default.memo(({ closeToast }) => {
|
|
2378
|
+
const { theme } = useTheme();
|
|
2379
|
+
const handleClick = (0, import_react11.useCallback)((e) => {
|
|
2380
|
+
e.preventDefault();
|
|
2381
|
+
e.stopPropagation();
|
|
2382
|
+
closeToast?.();
|
|
2383
|
+
}, [closeToast]);
|
|
2384
|
+
const getCloseButtonColor = () => {
|
|
2385
|
+
const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
|
|
2386
|
+
return actualTheme === "dark" ? "#b4b4b4" : "#6b7280";
|
|
2387
|
+
};
|
|
2388
|
+
const getCloseButtonHoverColor = () => {
|
|
2389
|
+
const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
|
|
2390
|
+
return actualTheme === "dark" ? "white" : "#374151";
|
|
2391
|
+
};
|
|
2392
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2393
|
+
import_react12.Icon,
|
|
2394
|
+
{
|
|
2395
|
+
icon: "vaadin:close",
|
|
2396
|
+
className: "flex items-center justify-center rounded-full relative z-10 flex-shrink-0 cursor-pointer transition-colors duration-200 drop-shadow-sm",
|
|
2397
|
+
onClick: handleClick,
|
|
2398
|
+
width: 14,
|
|
2399
|
+
height: 14,
|
|
2400
|
+
style: {
|
|
2401
|
+
color: getCloseButtonColor()
|
|
2402
|
+
},
|
|
2403
|
+
onMouseEnter: (e) => {
|
|
2404
|
+
e.currentTarget.style.color = getCloseButtonHoverColor();
|
|
2405
|
+
},
|
|
2406
|
+
onMouseLeave: (e) => {
|
|
2407
|
+
e.currentTarget.style.color = getCloseButtonColor();
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
);
|
|
2411
|
+
});
|
|
2412
|
+
CloseButton.displayName = "CloseButton";
|
|
2413
|
+
var ToastContent = ({ type, title, message, component, closeToast }) => {
|
|
2414
|
+
const iconConfig = TOAST_ICONS[type];
|
|
2415
|
+
const { theme } = useTheme();
|
|
2416
|
+
const handleClose = (0, import_react11.useCallback)(() => {
|
|
2417
|
+
closeToast?.();
|
|
2418
|
+
}, [closeToast]);
|
|
2419
|
+
const getTextColor = () => {
|
|
2420
|
+
const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
|
|
2421
|
+
return actualTheme === "dark" ? "white" : "#1f2937";
|
|
2422
|
+
};
|
|
2423
|
+
const getThemeConfig = () => {
|
|
2424
|
+
const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
|
|
2425
|
+
return actualTheme === "dark" ? iconConfig.dark : iconConfig.light;
|
|
2426
|
+
};
|
|
2427
|
+
const themeConfig = getThemeConfig();
|
|
2428
|
+
const lightBaseBackgroundByType = {
|
|
2429
|
+
success: "#f0fdf4",
|
|
2430
|
+
error: "#fef2f2",
|
|
2431
|
+
warning: "#fffbeb",
|
|
2432
|
+
info: "#eff6ff",
|
|
2433
|
+
default: "#f9fafb"
|
|
2434
|
+
};
|
|
2435
|
+
if (component) {
|
|
2436
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `flex items-start gap-3 !min-h-[90px] w-full backdrop-blur-md p-4 shadow-2xl overflow-hidden ${themeConfig.bgGradient}`, children: [
|
|
2437
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex-1 relative z-10", children: component }),
|
|
2438
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "relative z-10", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CloseButton, { closeToast: handleClose }) })
|
|
2439
|
+
] });
|
|
2440
|
+
}
|
|
2441
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `flex items-start gap-3 !min-h-[90px] w-full backdrop-blur-md p-4 shadow-2xl relative overflow-hidden ${themeConfig.bgGradient}`, children: [
|
|
1965
2442
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1966
2443
|
"div",
|
|
1967
2444
|
{
|
|
1968
|
-
className: "absolute left-0 top-0 w-full h-full rounded-
|
|
2445
|
+
className: "absolute left-0 top-0 w-full h-full rounded-xl",
|
|
1969
2446
|
style: {
|
|
1970
|
-
background: "#0f1419",
|
|
2447
|
+
background: theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "#0f1419" : lightBaseBackgroundByType[type],
|
|
1971
2448
|
zIndex: -2
|
|
1972
2449
|
}
|
|
1973
2450
|
}
|
|
@@ -1975,9 +2452,9 @@ var LimitToastContainer = ({ message, onUpgrade, closeToast }) => {
|
|
|
1975
2452
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1976
2453
|
"div",
|
|
1977
2454
|
{
|
|
1978
|
-
className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-
|
|
2455
|
+
className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-xl",
|
|
1979
2456
|
style: {
|
|
1980
|
-
background: `linear-gradient(135deg,
|
|
2457
|
+
background: theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? `linear-gradient(135deg, ${themeConfig.gradientColor}30 0%, ${themeConfig.gradientColor}20 15%, #14181df2 30%)` : `linear-gradient(135deg, ${themeConfig.gradientColor}20 0%, ${themeConfig.gradientColor}12 15%, #ffffff 30%)`,
|
|
1981
2458
|
zIndex: -1
|
|
1982
2459
|
}
|
|
1983
2460
|
}
|
|
@@ -1985,443 +2462,246 @@ var LimitToastContainer = ({ message, onUpgrade, closeToast }) => {
|
|
|
1985
2462
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1986
2463
|
"div",
|
|
1987
2464
|
{
|
|
1988
|
-
className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-
|
|
2465
|
+
className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-xl",
|
|
1989
2466
|
style: {
|
|
1990
2467
|
border: "2px solid transparent",
|
|
1991
|
-
backgroundImage: `linear-gradient(135deg,
|
|
2468
|
+
backgroundImage: theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? `linear-gradient(135deg, ${themeConfig.borderGradientColor}60 0%, ${themeConfig.borderGradientColor}40 5%, transparent 22%)` : `linear-gradient(135deg, ${themeConfig.borderGradientColor}99 0%, ${themeConfig.borderGradientColor}66 5%, transparent 22%)`,
|
|
1992
2469
|
backgroundOrigin: "border-box",
|
|
1993
2470
|
backgroundClip: "border-box",
|
|
1994
|
-
WebkitMask: "linear-gradient(#
|
|
2471
|
+
WebkitMask: "linear-gradient(#ffffff 0 0) padding-box, linear-gradient(#ffffff 0 0)",
|
|
1995
2472
|
WebkitMaskComposite: "xor",
|
|
1996
|
-
|
|
1997
|
-
maskComposite: "exclude"
|
|
2473
|
+
zIndex: 0
|
|
1998
2474
|
}
|
|
1999
2475
|
}
|
|
2000
2476
|
),
|
|
2001
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
onMouseLeave: () => setCloseHover(false),
|
|
2017
|
-
style: {
|
|
2018
|
-
height: "1.5rem",
|
|
2019
|
-
width: "1.5rem",
|
|
2020
|
-
minWidth: "1.5rem",
|
|
2021
|
-
borderRadius: "9999px",
|
|
2022
|
-
backgroundColor: closeHover ? "rgba(255,255,255,0.1)" : "rgba(255,255,255,0.05)",
|
|
2023
|
-
transition: "background-color 150ms ease",
|
|
2024
|
-
cursor: "pointer"
|
|
2025
|
-
},
|
|
2026
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react12.Icon, { icon: "iconamoon:close", className: "w-4 h-4 text-gray-400" })
|
|
2027
|
-
}
|
|
2028
|
-
)
|
|
2029
|
-
] }),
|
|
2030
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-gray-300 leading-relaxed", children: message }),
|
|
2031
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-1 flex items-center gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2032
|
-
ClayxButton,
|
|
2477
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex-shrink-0 mt-0.5 relative z-10", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: `w-7 h-7 backdrop-blur-sm rounded-full flex items-center justify-center ${theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "bg-white/10" : "bg-black/5"}`, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2478
|
+
import_react12.Icon,
|
|
2479
|
+
{
|
|
2480
|
+
icon: iconConfig.icon,
|
|
2481
|
+
width: 16,
|
|
2482
|
+
height: 16,
|
|
2483
|
+
className: iconConfig.color,
|
|
2484
|
+
style: {
|
|
2485
|
+
color: themeConfig.gradientColor
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
) }) }),
|
|
2489
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-1 flex-1 relative z-10", children: [
|
|
2490
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2491
|
+
"div",
|
|
2033
2492
|
{
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2493
|
+
className: "text-[16px] font-semibold leading-tight drop-shadow-sm",
|
|
2494
|
+
style: {
|
|
2495
|
+
color: getTextColor(),
|
|
2496
|
+
backgroundClip: "text"
|
|
2037
2497
|
},
|
|
2038
|
-
|
|
2039
|
-
|
|
2498
|
+
children: title
|
|
2499
|
+
}
|
|
2500
|
+
),
|
|
2501
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2502
|
+
"div",
|
|
2503
|
+
{
|
|
2504
|
+
className: "text-[13px] font-normal leading-relaxed drop-shadow-sm",
|
|
2040
2505
|
style: {
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
fontWeight: 600,
|
|
2044
|
-
cursor: "pointer",
|
|
2045
|
-
transition: "all 300ms ease-in-out",
|
|
2046
|
-
backgroundImage: hover ? "linear-gradient(to right, #9333ea, #db2777)" : "linear-gradient(to right, #a855f7, #ec4899)",
|
|
2047
|
-
boxShadow: hover ? "0 10px 15px -3px rgba(168,85,247,0.3), 0 4px 6px -2px rgba(168,85,247,0.3)" : "none"
|
|
2506
|
+
color: getTextColor(),
|
|
2507
|
+
backgroundClip: "text"
|
|
2048
2508
|
},
|
|
2049
|
-
children:
|
|
2050
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react12.Icon, { icon: "solar:rocket-2-bold", className: "w-4 h-4" }),
|
|
2051
|
-
"Upgrade Now"
|
|
2052
|
-
] })
|
|
2509
|
+
children: message
|
|
2053
2510
|
}
|
|
2054
|
-
)
|
|
2055
|
-
] })
|
|
2511
|
+
)
|
|
2512
|
+
] }),
|
|
2513
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "relative z-10", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CloseButton, { closeToast: handleClose }) })
|
|
2056
2514
|
] });
|
|
2057
2515
|
};
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
var
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
}
|
|
2075
|
-
buildHeaders(extra) {
|
|
2076
|
-
const h = { ...this.headers, ...extra || {} };
|
|
2077
|
-
if (this.apiKey && !h["Authorization"]) {
|
|
2078
|
-
h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
2079
|
-
}
|
|
2080
|
-
return h;
|
|
2081
|
-
}
|
|
2082
|
-
async safeJson(resp) {
|
|
2083
|
-
try {
|
|
2084
|
-
return await resp.json();
|
|
2085
|
-
} catch (_e) {
|
|
2086
|
-
return null;
|
|
2087
|
-
}
|
|
2088
|
-
}
|
|
2089
|
-
/**
|
|
2090
|
-
* 按 ID 执行工作流:POST {baseUrl}/workflow/{workflowId}/execute
|
|
2091
|
-
* body: { input, options }
|
|
2092
|
-
*/
|
|
2093
|
-
async executeWorkflow(workflowId, inputs, options) {
|
|
2094
|
-
if (!this.baseUrl) {
|
|
2095
|
-
throw new Error("AI workflow client requires a baseUrl (e.g. https://evoagentx-server.fly.dev)");
|
|
2096
|
-
}
|
|
2097
|
-
const url = `${this.baseUrl}/workflow/${workflowId}/execute`;
|
|
2098
|
-
try {
|
|
2099
|
-
const res = await this.fetchImpl(url, {
|
|
2100
|
-
method: "POST",
|
|
2101
|
-
headers: this.buildHeaders(),
|
|
2102
|
-
body: JSON.stringify({ inputs, options })
|
|
2103
|
-
});
|
|
2104
|
-
const data = await this.safeJson(res);
|
|
2105
|
-
if (!res.ok) {
|
|
2106
|
-
return { success: false, error: data?.error || `HTTP ${res.status}` };
|
|
2107
|
-
}
|
|
2108
|
-
if (data && data.status && data.status === 4003) {
|
|
2109
|
-
showLimitUpgradeToast(
|
|
2110
|
-
"Your credits are exhausted. Please upgrade your plan to continue generating projects.",
|
|
2111
|
-
() => window.open("https://clayx.ai/pricing", "_blank")
|
|
2112
|
-
);
|
|
2113
|
-
return null;
|
|
2114
|
-
}
|
|
2115
|
-
return data || { success: true };
|
|
2116
|
-
} catch (error) {
|
|
2117
|
-
return { success: false, error: error instanceof Error ? error.message : "Network error" };
|
|
2118
|
-
}
|
|
2516
|
+
var defaultToastOptions = {
|
|
2517
|
+
position: "bottom-right",
|
|
2518
|
+
autoClose: 3e3,
|
|
2519
|
+
hideProgressBar: true,
|
|
2520
|
+
closeOnClick: false,
|
|
2521
|
+
pauseOnHover: true,
|
|
2522
|
+
draggable: true,
|
|
2523
|
+
pauseOnFocusLoss: false,
|
|
2524
|
+
transition: import_react_toastify2.Bounce
|
|
2525
|
+
};
|
|
2526
|
+
var getToastifyTheme = () => {
|
|
2527
|
+
if (typeof window !== "undefined") {
|
|
2528
|
+
const root = document.documentElement;
|
|
2529
|
+
if (root.classList.contains("dark")) return "dark";
|
|
2530
|
+
if (root.classList.contains("light")) return "light";
|
|
2531
|
+
return window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
2119
2532
|
}
|
|
2533
|
+
return "light";
|
|
2120
2534
|
};
|
|
2121
|
-
|
|
2122
|
-
return
|
|
2123
|
-
}
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
this.interceptors = config.interceptors;
|
|
2139
|
-
this.instance.interceptors.request.use(
|
|
2140
|
-
this.interceptors?.requestInterceptor,
|
|
2141
|
-
this.interceptors?.requestInterceptorCatch
|
|
2142
|
-
);
|
|
2143
|
-
this.instance.interceptors.response.use(
|
|
2144
|
-
this.interceptors?.responseInterceptor,
|
|
2145
|
-
this.interceptors?.responseInterceptorCatch
|
|
2146
|
-
);
|
|
2147
|
-
this.instance.interceptors.request.use(
|
|
2148
|
-
(config2) => {
|
|
2149
|
-
return config2;
|
|
2150
|
-
},
|
|
2151
|
-
(err) => {
|
|
2152
|
-
return Promise.reject(err);
|
|
2153
|
-
}
|
|
2154
|
-
);
|
|
2155
|
-
this.instance.interceptors.response.use(
|
|
2156
|
-
(res) => {
|
|
2157
|
-
return res.data;
|
|
2535
|
+
var createToast = (type) => {
|
|
2536
|
+
return (params) => {
|
|
2537
|
+
const { title, message, component, options } = params;
|
|
2538
|
+
(0, import_react_toastify2.toast)(
|
|
2539
|
+
({ closeToast }) => {
|
|
2540
|
+
if (params.render) return params.render(closeToast ?? (() => {
|
|
2541
|
+
}));
|
|
2542
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2543
|
+
ToastContent,
|
|
2544
|
+
{
|
|
2545
|
+
type,
|
|
2546
|
+
title,
|
|
2547
|
+
message: message || "",
|
|
2548
|
+
component,
|
|
2549
|
+
closeToast
|
|
2550
|
+
}
|
|
2551
|
+
);
|
|
2158
2552
|
},
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
});
|
|
2166
|
-
}
|
|
2167
|
-
if (err.response?.data?.error) {
|
|
2168
|
-
return Promise.reject(err.response.data.error);
|
|
2169
|
-
}
|
|
2170
|
-
return Promise.reject(err);
|
|
2553
|
+
{
|
|
2554
|
+
...defaultToastOptions,
|
|
2555
|
+
...options,
|
|
2556
|
+
theme: getToastifyTheme(),
|
|
2557
|
+
className: "!p-0 !shadow-none !rounded-xl",
|
|
2558
|
+
style: { padding: 0, borderRadius: "0.75rem" }
|
|
2171
2559
|
}
|
|
2172
2560
|
);
|
|
2173
|
-
}
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
}
|
|
2182
|
-
cancelAllRequests() {
|
|
2183
|
-
this.abortControllers.forEach((controller) => {
|
|
2184
|
-
controller.abort();
|
|
2185
|
-
});
|
|
2186
|
-
this.abortControllers.clear();
|
|
2187
|
-
}
|
|
2188
|
-
request(config) {
|
|
2189
|
-
const controller = new AbortController();
|
|
2190
|
-
const url = config.url || "";
|
|
2191
|
-
const method = config.method || "GET";
|
|
2192
|
-
const key = `${method}:${url}`;
|
|
2193
|
-
this.abortControllers.set(key, controller);
|
|
2194
|
-
config.signal = controller.signal;
|
|
2195
|
-
return new Promise((resolve, reject) => {
|
|
2196
|
-
if (config.interceptors?.requestInterceptor) {
|
|
2197
|
-
config = config.interceptors.requestInterceptor(config);
|
|
2198
|
-
}
|
|
2199
|
-
this.instance.request(config).then((res) => {
|
|
2200
|
-
this.abortControllers.delete(key);
|
|
2201
|
-
if (config.interceptors?.responseInterceptor) {
|
|
2202
|
-
res = config.interceptors.responseInterceptor(res);
|
|
2203
|
-
}
|
|
2204
|
-
resolve(res);
|
|
2205
|
-
}).catch((err) => {
|
|
2206
|
-
this.abortControllers.delete(key);
|
|
2207
|
-
reject(err);
|
|
2208
|
-
});
|
|
2209
|
-
});
|
|
2210
|
-
}
|
|
2211
|
-
get(config) {
|
|
2212
|
-
return this.request({ ...config, method: "GET" });
|
|
2213
|
-
}
|
|
2214
|
-
post(config) {
|
|
2215
|
-
return this.request({ ...config, method: "POST" });
|
|
2216
|
-
}
|
|
2217
|
-
delete(config) {
|
|
2218
|
-
return this.request({ ...config, method: "DELETE" });
|
|
2219
|
-
}
|
|
2220
|
-
put(config) {
|
|
2221
|
-
return this.request({ ...config, method: "PUT" });
|
|
2222
|
-
}
|
|
2223
|
-
patch(config) {
|
|
2224
|
-
return this.request({ ...config, method: "PATCH" });
|
|
2225
|
-
}
|
|
2561
|
+
};
|
|
2562
|
+
};
|
|
2563
|
+
var ClayxToast = {
|
|
2564
|
+
success: createToast("success"),
|
|
2565
|
+
error: createToast("error"),
|
|
2566
|
+
warning: createToast("warning"),
|
|
2567
|
+
info: createToast("info"),
|
|
2568
|
+
default: createToast("default")
|
|
2226
2569
|
};
|
|
2227
|
-
var request_default = Request;
|
|
2228
2570
|
|
|
2229
|
-
// src/
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
const
|
|
2233
|
-
const
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2571
|
+
// src/components/ui/LimitUpgradeToast.tsx
|
|
2572
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2573
|
+
var LimitToastContainer = ({ message, onUpgrade, closeToast }) => {
|
|
2574
|
+
const [hover, setHover] = import_react13.default.useState(false);
|
|
2575
|
+
const [closeHover, setCloseHover] = import_react13.default.useState(false);
|
|
2576
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "relative w-full max-w-[420px] overflow-hidden rounded-md bg-gradient-to-br from-[#1A1A1A] via-[#151515] to-[#1A1A1A] shadow-[0_20px_60px_rgba(168,85,247,0.2)] backdrop-blur-sm", children: [
|
|
2577
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2578
|
+
"div",
|
|
2579
|
+
{
|
|
2580
|
+
className: "absolute left-0 top-0 w-full h-full rounded-md",
|
|
2581
|
+
style: {
|
|
2582
|
+
background: "#0f1419",
|
|
2583
|
+
zIndex: -2
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
),
|
|
2587
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2588
|
+
"div",
|
|
2589
|
+
{
|
|
2590
|
+
className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-md",
|
|
2591
|
+
style: {
|
|
2592
|
+
background: `linear-gradient(135deg, rgba(168,85,247,0.3) 0%, rgba(168,85,247,0.2) 15%, #1A1A1A 30%)`,
|
|
2593
|
+
zIndex: -1
|
|
2242
2594
|
}
|
|
2243
|
-
|
|
2244
|
-
|
|
2595
|
+
}
|
|
2596
|
+
),
|
|
2597
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2598
|
+
"div",
|
|
2599
|
+
{
|
|
2600
|
+
className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-md",
|
|
2601
|
+
style: {
|
|
2602
|
+
border: "2px solid transparent",
|
|
2603
|
+
backgroundImage: `linear-gradient(135deg, rgba(168,85,247,0.6) 0%, rgba(168,85,247,0.4) 5%, transparent 22%)`,
|
|
2604
|
+
backgroundOrigin: "border-box",
|
|
2605
|
+
backgroundClip: "border-box",
|
|
2606
|
+
WebkitMask: "linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)",
|
|
2607
|
+
WebkitMaskComposite: "xor",
|
|
2608
|
+
mask: "linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)",
|
|
2609
|
+
maskComposite: "exclude"
|
|
2245
2610
|
}
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2611
|
+
}
|
|
2612
|
+
),
|
|
2613
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "absolute -top-16 -right-16 h-32 w-32 rounded-full bg-gradient-to-br from-purple-500/20 via-pink-500/10 to-transparent blur-3xl animate-pulse" }),
|
|
2614
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "absolute -bottom-16 -left-16 h-32 w-32 rounded-full bg-gradient-to-tr from-blue-500/10 to-transparent blur-2xl animate-pulse", style: { animationDelay: "1s" } }),
|
|
2615
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "relative z-10 flex items-start gap-4 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-1 flex-col gap-3", children: [
|
|
2616
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2617
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2618
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "text-lg font-bold text-white", children: "Upgrade Required" }),
|
|
2619
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "px-2 py-0.5 text-xs font-bold bg-purple-500/20 text-purple-400 rounded-md border border-purple-500/30", children: "Premium" })
|
|
2620
|
+
] }),
|
|
2621
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2622
|
+
ClayxButton,
|
|
2623
|
+
{
|
|
2624
|
+
onClick: closeToast,
|
|
2625
|
+
isIconOnly: true,
|
|
2626
|
+
size: "sm",
|
|
2627
|
+
onMouseEnter: () => setCloseHover(true),
|
|
2628
|
+
onMouseLeave: () => setCloseHover(false),
|
|
2629
|
+
style: {
|
|
2630
|
+
height: "1.5rem",
|
|
2631
|
+
width: "1.5rem",
|
|
2632
|
+
minWidth: "1.5rem",
|
|
2633
|
+
borderRadius: "9999px",
|
|
2634
|
+
backgroundColor: closeHover ? "rgba(255,255,255,0.1)" : "rgba(255,255,255,0.05)",
|
|
2635
|
+
transition: "background-color 150ms ease",
|
|
2636
|
+
cursor: "pointer"
|
|
2637
|
+
},
|
|
2638
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react14.Icon, { icon: "iconamoon:close", className: "w-4 h-4 text-gray-400" })
|
|
2639
|
+
}
|
|
2640
|
+
)
|
|
2641
|
+
] }),
|
|
2642
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-sm text-gray-300 leading-relaxed", children: message }),
|
|
2643
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-1 flex items-center gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2644
|
+
ClayxButton,
|
|
2645
|
+
{
|
|
2646
|
+
onClick: () => {
|
|
2647
|
+
onUpgrade();
|
|
2648
|
+
closeToast?.();
|
|
2649
|
+
},
|
|
2650
|
+
onMouseEnter: () => setHover(true),
|
|
2651
|
+
onMouseLeave: () => setHover(false),
|
|
2652
|
+
style: {
|
|
2653
|
+
flex: 1,
|
|
2654
|
+
color: "#ffffff",
|
|
2655
|
+
fontWeight: 600,
|
|
2656
|
+
cursor: "pointer",
|
|
2657
|
+
transition: "all 300ms ease-in-out",
|
|
2658
|
+
backgroundImage: hover ? "linear-gradient(to right, #9333ea, #db2777)" : "linear-gradient(to right, #a855f7, #ec4899)",
|
|
2659
|
+
boxShadow: hover ? "0 10px 15px -3px rgba(168,85,247,0.3), 0 4px 6px -2px rgba(168,85,247,0.3)" : "none"
|
|
2660
|
+
},
|
|
2661
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "flex items-center gap-2", children: [
|
|
2662
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react14.Icon, { icon: "solar:rocket-2-bold", className: "w-4 h-4" }),
|
|
2663
|
+
"Upgrade Now"
|
|
2664
|
+
] })
|
|
2665
|
+
}
|
|
2666
|
+
) })
|
|
2667
|
+
] }) })
|
|
2668
|
+
] });
|
|
2669
|
+
};
|
|
2670
|
+
function showLimitUpgradeToast(message, onUpgrade) {
|
|
2671
|
+
ClayxToast.default({
|
|
2672
|
+
render: (closeToast) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LimitToastContainer, { message, onUpgrade, closeToast }),
|
|
2673
|
+
options: {
|
|
2674
|
+
autoClose: false
|
|
2251
2675
|
}
|
|
2252
2676
|
});
|
|
2253
|
-
return {
|
|
2254
|
-
async executeWorkflow(workflowId, inputs, opts) {
|
|
2255
|
-
const url = `${baseUrl}/workflow/${workflowId}/execute`;
|
|
2256
|
-
const data = await client.post({ url, data: { inputs, options: opts } });
|
|
2257
|
-
return data;
|
|
2258
|
-
}
|
|
2259
|
-
};
|
|
2260
2677
|
}
|
|
2261
2678
|
|
|
2262
|
-
// src/services/
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
return false;
|
|
2270
|
-
}
|
|
2271
|
-
if (a.visibility === "private") {
|
|
2272
|
-
if (ctx.userId && a.ownerId && ctx.userId === a.ownerId) return true;
|
|
2273
|
-
if (ctx.tokenScopes && (ctx.tokenScopes.includes("artifact:read:all") || ctx.tokenScopes.includes("admin"))) return true;
|
|
2274
|
-
return false;
|
|
2275
|
-
}
|
|
2276
|
-
if (a.visibility === "shared") {
|
|
2277
|
-
if (ctx.userId && a.sharedWith && a.sharedWith.includes(ctx.userId)) return true;
|
|
2278
|
-
if (ctx.tokenScopes && (ctx.tokenScopes.includes("artifact:read:all") || ctx.tokenScopes.includes("admin"))) return true;
|
|
2279
|
-
return false;
|
|
2679
|
+
// src/services/limit-exceeded.ts
|
|
2680
|
+
init_config();
|
|
2681
|
+
var DEFAULT_LIMIT_EXCEEDED_MESSAGE = "Your credits are exhausted. Please upgrade your plan to continue generating projects.";
|
|
2682
|
+
function handleLimitExceeded(context, options) {
|
|
2683
|
+
options?.onLimitExceeded?.(context);
|
|
2684
|
+
if (options?.showUpgradeToast === false) {
|
|
2685
|
+
return;
|
|
2280
2686
|
}
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
return {
|
|
2287
|
-
async create(input) {
|
|
2288
|
-
return await req.post({ url: "/artifacts", data: input });
|
|
2289
|
-
},
|
|
2290
|
-
async list(query) {
|
|
2291
|
-
return await req.get({ url: "/artifacts", params: query });
|
|
2292
|
-
},
|
|
2293
|
-
async get(id) {
|
|
2294
|
-
return await req.get({ url: `/artifacts/${encodeURIComponent(id)}` });
|
|
2295
|
-
},
|
|
2296
|
-
async setVisibility(id, visibility) {
|
|
2297
|
-
await req.patch({ url: `/artifacts/${encodeURIComponent(id)}/visibility`, data: { visibility } });
|
|
2298
|
-
},
|
|
2299
|
-
async delete(id) {
|
|
2300
|
-
await req.delete({ url: `/artifacts/${encodeURIComponent(id)}` });
|
|
2301
|
-
},
|
|
2302
|
-
// convenience local check (server is authoritative)
|
|
2303
|
-
canAccessLocal(a, ctx) {
|
|
2304
|
-
if (!a) return false;
|
|
2305
|
-
if (a.visibility === "public") return true;
|
|
2306
|
-
if (a.visibility === "project") return Boolean(ctx.projectId && a.projectId && ctx.projectId === a.projectId);
|
|
2307
|
-
if (a.visibility === "private") return Boolean(ctx.userId && a.ownerId && ctx.userId === a.ownerId);
|
|
2308
|
-
if (a.visibility === "shared") return Boolean(ctx.userId && a.sharedWith && a.sharedWith.includes(ctx.userId));
|
|
2309
|
-
return false;
|
|
2310
|
-
}
|
|
2311
|
-
};
|
|
2687
|
+
const upgradeUrl = options?.upgradeUrl || `${getEnvs().AUTH_ROOT_VALUE}/price`;
|
|
2688
|
+
showLimitUpgradeToast(
|
|
2689
|
+
context.message || DEFAULT_LIMIT_EXCEEDED_MESSAGE,
|
|
2690
|
+
() => window.open(upgradeUrl, "_blank")
|
|
2691
|
+
);
|
|
2312
2692
|
}
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2693
|
+
function mergeLimitExceededOptions(base, override) {
|
|
2694
|
+
if (!base && !override) {
|
|
2695
|
+
return void 0;
|
|
2696
|
+
}
|
|
2317
2697
|
return {
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
* @example
|
|
2322
|
-
* ```typescript
|
|
2323
|
-
* const { url } = await client.upload.file(imageFile)
|
|
2324
|
-
* console.log('文件地址:', url)
|
|
2325
|
-
* ```
|
|
2326
|
-
*/
|
|
2327
|
-
async file(file, options) {
|
|
2328
|
-
const formData = new FormData();
|
|
2329
|
-
if (typeof file === "string") {
|
|
2330
|
-
if (file.startsWith("data:")) {
|
|
2331
|
-
const response2 = await fetch(file);
|
|
2332
|
-
const blob = await response2.blob();
|
|
2333
|
-
formData.append("file", blob, "upload.bin");
|
|
2334
|
-
} else {
|
|
2335
|
-
formData.append("fileUrl", file);
|
|
2336
|
-
}
|
|
2337
|
-
} else if (file instanceof File) {
|
|
2338
|
-
formData.append("file", file, file.name);
|
|
2339
|
-
} else {
|
|
2340
|
-
formData.append("file", file, "upload.bin");
|
|
2341
|
-
}
|
|
2342
|
-
if (options?.metadata) {
|
|
2343
|
-
formData.append("metadata", JSON.stringify(options.metadata));
|
|
2344
|
-
}
|
|
2345
|
-
const response = await req.post({
|
|
2346
|
-
url: uploadUrl,
|
|
2347
|
-
data: formData,
|
|
2348
|
-
signal: options?.signal
|
|
2349
|
-
});
|
|
2350
|
-
return {
|
|
2351
|
-
url: response.data.publicUrl
|
|
2352
|
-
};
|
|
2353
|
-
},
|
|
2354
|
-
/**
|
|
2355
|
-
* 上传图片(快捷方法,专为 AI 设计)
|
|
2356
|
-
*
|
|
2357
|
-
* @example
|
|
2358
|
-
* ```typescript
|
|
2359
|
-
* const { url } = await client.upload.image(imageFile)
|
|
2360
|
-
* ```
|
|
2361
|
-
*/
|
|
2362
|
-
async image(file) {
|
|
2363
|
-
const result = await this.file(file);
|
|
2364
|
-
return { url: result.url };
|
|
2365
|
-
},
|
|
2366
|
-
/**
|
|
2367
|
-
* 批量上传文件
|
|
2368
|
-
*
|
|
2369
|
-
* @example
|
|
2370
|
-
* ```typescript
|
|
2371
|
-
* const result = await client.upload.batch({
|
|
2372
|
-
* files: [file1, file2, file3],
|
|
2373
|
-
* concurrent: 3,
|
|
2374
|
-
* onProgress: (completed, total) => {
|
|
2375
|
-
* console.log(`${completed}/${total}`)
|
|
2376
|
-
* }
|
|
2377
|
-
* })
|
|
2378
|
-
* ```
|
|
2379
|
-
*/
|
|
2380
|
-
async batch(options) {
|
|
2381
|
-
const { files, concurrent = 3, onProgress, onFileComplete, signal } = options;
|
|
2382
|
-
const success = [];
|
|
2383
|
-
const failed = [];
|
|
2384
|
-
let completed = 0;
|
|
2385
|
-
for (let i = 0; i < files.length; i += concurrent) {
|
|
2386
|
-
if (signal?.aborted) break;
|
|
2387
|
-
const batch = files.slice(i, Math.min(i + concurrent, files.length));
|
|
2388
|
-
const promises = batch.map(async (file, batchIndex) => {
|
|
2389
|
-
const globalIndex = i + batchIndex;
|
|
2390
|
-
try {
|
|
2391
|
-
const result = await this.file(file, { signal });
|
|
2392
|
-
success.push(result);
|
|
2393
|
-
if (onFileComplete) {
|
|
2394
|
-
onFileComplete(result, globalIndex);
|
|
2395
|
-
}
|
|
2396
|
-
} catch (error) {
|
|
2397
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2398
|
-
failed.push({ index: globalIndex, error: errorMsg });
|
|
2399
|
-
if (onFileComplete) {
|
|
2400
|
-
onFileComplete(
|
|
2401
|
-
error instanceof Error ? error : new Error(errorMsg),
|
|
2402
|
-
globalIndex
|
|
2403
|
-
);
|
|
2404
|
-
}
|
|
2405
|
-
} finally {
|
|
2406
|
-
completed++;
|
|
2407
|
-
if (onProgress) {
|
|
2408
|
-
onProgress(completed, files.length);
|
|
2409
|
-
}
|
|
2410
|
-
}
|
|
2411
|
-
});
|
|
2412
|
-
await Promise.all(promises);
|
|
2413
|
-
}
|
|
2414
|
-
return {
|
|
2415
|
-
success,
|
|
2416
|
-
failed,
|
|
2417
|
-
total: files.length
|
|
2418
|
-
};
|
|
2419
|
-
}
|
|
2698
|
+
...base,
|
|
2699
|
+
...override,
|
|
2700
|
+
onLimitExceeded: override?.onLimitExceeded ?? base?.onLimitExceeded
|
|
2420
2701
|
};
|
|
2421
2702
|
}
|
|
2422
2703
|
|
|
2423
2704
|
// src/services/sse-executor.ts
|
|
2424
|
-
init_config();
|
|
2425
2705
|
async function executeSSEWorkflow(request, options = {}) {
|
|
2426
2706
|
const startTime = Date.now();
|
|
2427
2707
|
const result = {
|
|
@@ -2512,7 +2792,7 @@ async function executeSSEWorkflow(request, options = {}) {
|
|
|
2512
2792
|
if (errorData.log_type === "execution_display_error") {
|
|
2513
2793
|
const errorContent = errorData.content;
|
|
2514
2794
|
const displayMessage = errorContent || "Workflow execution failed";
|
|
2515
|
-
|
|
2795
|
+
ClayxToast.error({
|
|
2516
2796
|
title: "Execution Error",
|
|
2517
2797
|
message: displayMessage
|
|
2518
2798
|
});
|
|
@@ -2522,11 +2802,16 @@ async function executeSSEWorkflow(request, options = {}) {
|
|
|
2522
2802
|
options.onStreamContent(rawEvent.delta);
|
|
2523
2803
|
}
|
|
2524
2804
|
if (rawEvent.type === "key_limit_exceed") {
|
|
2525
|
-
const errorMsg = rawEvent.data
|
|
2805
|
+
const errorMsg = rawEvent.data?.content || DEFAULT_LIMIT_EXCEEDED_MESSAGE;
|
|
2526
2806
|
result.errors.push(errorMsg);
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2807
|
+
handleLimitExceeded(
|
|
2808
|
+
{
|
|
2809
|
+
source: "sse-executor",
|
|
2810
|
+
message: errorMsg,
|
|
2811
|
+
eventType: rawEvent.type,
|
|
2812
|
+
rawData: rawEvent.data
|
|
2813
|
+
},
|
|
2814
|
+
options.limitExceeded
|
|
2530
2815
|
);
|
|
2531
2816
|
if (options.onError) {
|
|
2532
2817
|
options.onError(new Error(errorMsg));
|
|
@@ -2737,7 +3022,7 @@ function createEventIterable(streamFactory, config) {
|
|
|
2737
3022
|
};
|
|
2738
3023
|
}
|
|
2739
3024
|
function createSSEClient(config) {
|
|
2740
|
-
const { baseUrl, projectId, getAuthToken } = config;
|
|
3025
|
+
const { baseUrl, projectId, getAuthToken, limitExceeded } = config;
|
|
2741
3026
|
const stream = (streamConfig) => {
|
|
2742
3027
|
const { signal: externalSignal, ...callbacks } = streamConfig;
|
|
2743
3028
|
const request = resolveRequest(baseUrl, projectId, streamConfig);
|
|
@@ -2753,7 +3038,11 @@ function createSSEClient(config) {
|
|
|
2753
3038
|
{
|
|
2754
3039
|
...callbacks,
|
|
2755
3040
|
authToken,
|
|
2756
|
-
signal: controller.signal
|
|
3041
|
+
signal: controller.signal,
|
|
3042
|
+
limitExceeded: mergeLimitExceededOptions(
|
|
3043
|
+
limitExceeded,
|
|
3044
|
+
streamConfig.limitExceeded
|
|
3045
|
+
)
|
|
2757
3046
|
}
|
|
2758
3047
|
).finally(() => {
|
|
2759
3048
|
controller.cleanup();
|
|
@@ -2929,6 +3218,19 @@ async function executeWorkflowStreamPost(baseUrl, projectId, workflowId, request
|
|
|
2929
3218
|
break;
|
|
2930
3219
|
case "error":
|
|
2931
3220
|
throw new Error(event.message || "Workflow execution failed");
|
|
3221
|
+
case "key_limit_exceed": {
|
|
3222
|
+
const errorMessage = event?.data?.content || event.message || DEFAULT_LIMIT_EXCEEDED_MESSAGE;
|
|
3223
|
+
handleLimitExceeded(
|
|
3224
|
+
{
|
|
3225
|
+
source: "sse-executor",
|
|
3226
|
+
message: errorMessage,
|
|
3227
|
+
eventType: event.type,
|
|
3228
|
+
rawData: event.data
|
|
3229
|
+
},
|
|
3230
|
+
options.limitExceeded
|
|
3231
|
+
);
|
|
3232
|
+
throw new Error(errorMessage);
|
|
3233
|
+
}
|
|
2932
3234
|
}
|
|
2933
3235
|
} catch (err) {
|
|
2934
3236
|
console.error("Failed to parse SSE event:", err);
|
|
@@ -2947,12 +3249,12 @@ async function executeWorkflowStreamPost(baseUrl, projectId, workflowId, request
|
|
|
2947
3249
|
}
|
|
2948
3250
|
|
|
2949
3251
|
// src/services/workflow-executor.ts
|
|
2950
|
-
init_config();
|
|
2951
3252
|
var WorkflowExecutor = class {
|
|
2952
|
-
constructor(baseUrl, projectId, authToken) {
|
|
3253
|
+
constructor(baseUrl, projectId, authToken, limitExceeded) {
|
|
2953
3254
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
2954
3255
|
this.projectId = projectId;
|
|
2955
3256
|
this.authToken = authToken;
|
|
3257
|
+
this.limitExceeded = limitExceeded;
|
|
2956
3258
|
}
|
|
2957
3259
|
/**
|
|
2958
3260
|
* 执行工作流 (SSE 模式)
|
|
@@ -3002,6 +3304,10 @@ var WorkflowExecutor = class {
|
|
|
3002
3304
|
errors: []
|
|
3003
3305
|
};
|
|
3004
3306
|
let streamContent = "";
|
|
3307
|
+
const limitExceededOptions = mergeLimitExceededOptions(
|
|
3308
|
+
this.limitExceeded,
|
|
3309
|
+
options?.limitExceeded
|
|
3310
|
+
);
|
|
3005
3311
|
try {
|
|
3006
3312
|
const response = await fetch(url, {
|
|
3007
3313
|
method: "POST",
|
|
@@ -3054,11 +3360,16 @@ var WorkflowExecutor = class {
|
|
|
3054
3360
|
}
|
|
3055
3361
|
}
|
|
3056
3362
|
} else if (event.type === "key_limit_exceed") {
|
|
3057
|
-
const errorMsg = event.data?.content;
|
|
3363
|
+
const errorMsg = event.data?.content || DEFAULT_LIMIT_EXCEEDED_MESSAGE;
|
|
3058
3364
|
result.errors.push(errorMsg);
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3365
|
+
handleLimitExceeded(
|
|
3366
|
+
{
|
|
3367
|
+
source: "workflow-executor-sse",
|
|
3368
|
+
message: errorMsg,
|
|
3369
|
+
eventType: event.type,
|
|
3370
|
+
rawData: event.data
|
|
3371
|
+
},
|
|
3372
|
+
limitExceededOptions
|
|
3062
3373
|
);
|
|
3063
3374
|
if (options?.onError) {
|
|
3064
3375
|
options.onError(new Error(errorMsg));
|
|
@@ -3142,6 +3453,17 @@ var WorkflowExecutor = class {
|
|
|
3142
3453
|
body: JSON.stringify({ inputs })
|
|
3143
3454
|
});
|
|
3144
3455
|
const data = await response.json();
|
|
3456
|
+
if (data && data.status === 4003) {
|
|
3457
|
+
handleLimitExceeded(
|
|
3458
|
+
{
|
|
3459
|
+
source: "workflow-executor-rest",
|
|
3460
|
+
message: data?.error || data?.message || DEFAULT_LIMIT_EXCEEDED_MESSAGE,
|
|
3461
|
+
status: response.status,
|
|
3462
|
+
rawData: data
|
|
3463
|
+
},
|
|
3464
|
+
this.limitExceeded
|
|
3465
|
+
);
|
|
3466
|
+
}
|
|
3145
3467
|
return {
|
|
3146
3468
|
status: response.status,
|
|
3147
3469
|
data
|
|
@@ -3223,14 +3545,6 @@ function createClient(opts) {
|
|
|
3223
3545
|
},
|
|
3224
3546
|
requestInterceptorCatch: (err) => Promise.reject(err),
|
|
3225
3547
|
responseInterceptor: (res) => {
|
|
3226
|
-
const data = res.data;
|
|
3227
|
-
if (data && data.status && data.status === 4003) {
|
|
3228
|
-
showLimitUpgradeToast(
|
|
3229
|
-
"Your credits are exhausted. Please upgrade your plan to continue generating projects.",
|
|
3230
|
-
() => window.open(`${getEnvs().AUTH_ROOT_VALUE}/price`, "_blank")
|
|
3231
|
-
);
|
|
3232
|
-
return res;
|
|
3233
|
-
}
|
|
3234
3548
|
return res;
|
|
3235
3549
|
},
|
|
3236
3550
|
responseInterceptorCatch: (err) => Promise.reject(err)
|
|
@@ -3338,7 +3652,8 @@ function createClient(opts) {
|
|
|
3338
3652
|
void fetchExternalToken();
|
|
3339
3653
|
}
|
|
3340
3654
|
return token ?? cachedExternalToken ?? getToken() ?? null;
|
|
3341
|
-
}
|
|
3655
|
+
},
|
|
3656
|
+
limitExceeded: opts.limitExceeded
|
|
3342
3657
|
});
|
|
3343
3658
|
const assignMethod = (config, method) => method ? { ...config, method } : config;
|
|
3344
3659
|
function createMethodInvoker(invoker) {
|
|
@@ -3400,7 +3715,8 @@ function createClient(opts) {
|
|
|
3400
3715
|
const executor = new WorkflowExecutor(
|
|
3401
3716
|
actualAiBaseUrl,
|
|
3402
3717
|
opts.projectId,
|
|
3403
|
-
getCachedOrGlobalToken() ?? void 0
|
|
3718
|
+
getCachedOrGlobalToken() ?? void 0,
|
|
3719
|
+
opts.limitExceeded
|
|
3404
3720
|
);
|
|
3405
3721
|
return {
|
|
3406
3722
|
executeSse: (inputs, options) => {
|
|
@@ -3618,11 +3934,11 @@ function createClient(opts) {
|
|
|
3618
3934
|
}
|
|
3619
3935
|
|
|
3620
3936
|
// src/hooks/use-mobile.ts
|
|
3621
|
-
var
|
|
3937
|
+
var React9 = __toESM(require("react"));
|
|
3622
3938
|
var MOBILE_BREAKPOINT = 768;
|
|
3623
3939
|
function useIsMobile() {
|
|
3624
|
-
const [isMobile, setIsMobile] =
|
|
3625
|
-
|
|
3940
|
+
const [isMobile, setIsMobile] = React9.useState(void 0);
|
|
3941
|
+
React9.useEffect(() => {
|
|
3626
3942
|
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
3627
3943
|
const onChange = () => {
|
|
3628
3944
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
@@ -3635,10 +3951,10 @@ function useIsMobile() {
|
|
|
3635
3951
|
}
|
|
3636
3952
|
|
|
3637
3953
|
// src/hooks/use-debounce.ts
|
|
3638
|
-
var
|
|
3954
|
+
var import_react15 = require("react");
|
|
3639
3955
|
function useDebounce(value, delay) {
|
|
3640
|
-
const [debouncedValue, setDebouncedValue] = (0,
|
|
3641
|
-
(0,
|
|
3956
|
+
const [debouncedValue, setDebouncedValue] = (0, import_react15.useState)(value);
|
|
3957
|
+
(0, import_react15.useEffect)(() => {
|
|
3642
3958
|
const handler = setTimeout(() => {
|
|
3643
3959
|
setDebouncedValue(value);
|
|
3644
3960
|
}, delay);
|
|
@@ -3650,9 +3966,9 @@ function useDebounce(value, delay) {
|
|
|
3650
3966
|
}
|
|
3651
3967
|
|
|
3652
3968
|
// src/hooks/use-workflow-stream.ts
|
|
3653
|
-
var
|
|
3969
|
+
var import_react16 = require("react");
|
|
3654
3970
|
function useWorkflowStream() {
|
|
3655
|
-
const [state, setState] = (0,
|
|
3971
|
+
const [state, setState] = (0, import_react16.useState)({
|
|
3656
3972
|
loading: false,
|
|
3657
3973
|
progress: 0,
|
|
3658
3974
|
streamContent: "",
|
|
@@ -3660,8 +3976,8 @@ function useWorkflowStream() {
|
|
|
3660
3976
|
result: null,
|
|
3661
3977
|
error: null
|
|
3662
3978
|
});
|
|
3663
|
-
const abortControllerRef = (0,
|
|
3664
|
-
const execute = (0,
|
|
3979
|
+
const abortControllerRef = (0, import_react16.useRef)(null);
|
|
3980
|
+
const execute = (0, import_react16.useCallback)(async (executeWorkflowStream, workflowId, inputs) => {
|
|
3665
3981
|
setState({
|
|
3666
3982
|
loading: true,
|
|
3667
3983
|
progress: 0,
|
|
@@ -3714,7 +4030,7 @@ function useWorkflowStream() {
|
|
|
3714
4030
|
throw error;
|
|
3715
4031
|
}
|
|
3716
4032
|
}, []);
|
|
3717
|
-
const cancel = (0,
|
|
4033
|
+
const cancel = (0, import_react16.useCallback)(() => {
|
|
3718
4034
|
if (abortControllerRef.current) {
|
|
3719
4035
|
abortControllerRef.current.abort();
|
|
3720
4036
|
setState((prev) => ({
|
|
@@ -3724,7 +4040,7 @@ function useWorkflowStream() {
|
|
|
3724
4040
|
}));
|
|
3725
4041
|
}
|
|
3726
4042
|
}, []);
|
|
3727
|
-
const reset = (0,
|
|
4043
|
+
const reset = (0, import_react16.useCallback)(() => {
|
|
3728
4044
|
setState({
|
|
3729
4045
|
loading: false,
|
|
3730
4046
|
progress: 0,
|
|
@@ -4030,13 +4346,14 @@ var elementSelector = {
|
|
|
4030
4346
|
0 && (module.exports = {
|
|
4031
4347
|
AUTH_TOKEN_KEY,
|
|
4032
4348
|
ClayxButton,
|
|
4349
|
+
ClayxToast,
|
|
4350
|
+
DEFAULT_LIMIT_EXCEEDED_MESSAGE,
|
|
4033
4351
|
DefaultErrorFallback,
|
|
4034
4352
|
ElementSelector,
|
|
4035
4353
|
ElementSelectorProvider,
|
|
4036
4354
|
ErrorBoundary,
|
|
4037
4355
|
FloatingButton,
|
|
4038
4356
|
GlobalToastContainer,
|
|
4039
|
-
GoeyToast,
|
|
4040
4357
|
HowOneProvider,
|
|
4041
4358
|
Loading,
|
|
4042
4359
|
LoadingSpinner,
|
|
@@ -4060,11 +4377,13 @@ var elementSelector = {
|
|
|
4060
4377
|
getEnvs,
|
|
4061
4378
|
getGlobalEnvironment,
|
|
4062
4379
|
getToken,
|
|
4380
|
+
handleLimitExceeded,
|
|
4063
4381
|
howone,
|
|
4064
4382
|
iframeNavigation,
|
|
4065
4383
|
initIframeNavigation,
|
|
4066
4384
|
isTokenValid,
|
|
4067
4385
|
loginWithEmailCode,
|
|
4386
|
+
mergeLimitExceededOptions,
|
|
4068
4387
|
onAuthStateChanged,
|
|
4069
4388
|
parseUserFromToken,
|
|
4070
4389
|
sendElementSelectionToParent,
|