@howone/sdk 0.7.0 → 0.7.2
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 +29 -3
- package/dist/index.d.ts +29 -3
- package/dist/index.js +503 -438
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +500 -438
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -298,6 +298,7 @@ __export(index_exports, {
|
|
|
298
298
|
AUTH_TOKEN_KEY: () => AUTH_TOKEN_KEY,
|
|
299
299
|
ClayxButton: () => ClayxButton,
|
|
300
300
|
ClayxToast: () => ClayxToast,
|
|
301
|
+
DEFAULT_LIMIT_EXCEEDED_MESSAGE: () => DEFAULT_LIMIT_EXCEEDED_MESSAGE,
|
|
301
302
|
DefaultErrorFallback: () => DefaultErrorFallback,
|
|
302
303
|
ElementSelector: () => ElementSelector,
|
|
303
304
|
ElementSelectorProvider: () => ElementSelectorProvider,
|
|
@@ -327,11 +328,13 @@ __export(index_exports, {
|
|
|
327
328
|
getEnvs: () => getEnvs,
|
|
328
329
|
getGlobalEnvironment: () => getGlobalEnvironment,
|
|
329
330
|
getToken: () => getToken,
|
|
331
|
+
handleLimitExceeded: () => handleLimitExceeded,
|
|
330
332
|
howone: () => client_default,
|
|
331
333
|
iframeNavigation: () => iframeNavigation,
|
|
332
334
|
initIframeNavigation: () => initIframeNavigation,
|
|
333
335
|
isTokenValid: () => isTokenValid,
|
|
334
336
|
loginWithEmailCode: () => loginWithEmailCode,
|
|
337
|
+
mergeLimitExceededOptions: () => mergeLimitExceededOptions,
|
|
335
338
|
onAuthStateChanged: () => onAuthStateChanged,
|
|
336
339
|
parseUserFromToken: () => parseUserFromToken,
|
|
337
340
|
sendElementSelectionToParent: () => sendElementSelectionToParent,
|
|
@@ -831,6 +834,355 @@ function getCodeStatus(email) {
|
|
|
831
834
|
return unifiedAuth.getCodeStatus(email);
|
|
832
835
|
}
|
|
833
836
|
|
|
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}` };
|
|
877
|
+
}
|
|
878
|
+
return data || { success: true };
|
|
879
|
+
} catch (error) {
|
|
880
|
+
return { success: false, error: error instanceof Error ? error.message : "Network error" };
|
|
881
|
+
}
|
|
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;
|
|
899
|
+
}
|
|
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);
|
|
916
|
+
}
|
|
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);
|
|
934
|
+
}
|
|
935
|
+
);
|
|
936
|
+
}
|
|
937
|
+
cancelRequest(url) {
|
|
938
|
+
this.abortControllers.forEach((controller, key) => {
|
|
939
|
+
if (key.includes(url)) {
|
|
940
|
+
controller.abort();
|
|
941
|
+
this.abortControllers.delete(key);
|
|
942
|
+
}
|
|
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
|
+
|
|
834
1186
|
// src/components/auth/LoginForm.tsx
|
|
835
1187
|
var import_react2 = require("react");
|
|
836
1188
|
var import_react3 = require("@iconify/react");
|
|
@@ -2254,434 +2606,102 @@ var LimitToastContainer = ({ message, onUpgrade, closeToast }) => {
|
|
|
2254
2606
|
WebkitMask: "linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)",
|
|
2255
2607
|
WebkitMaskComposite: "xor",
|
|
2256
2608
|
mask: "linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)",
|
|
2257
|
-
maskComposite: "exclude"
|
|
2258
|
-
}
|
|
2259
|
-
}
|
|
2260
|
-
),
|
|
2261
|
-
/* @__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" }),
|
|
2262
|
-
/* @__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" } }),
|
|
2263
|
-
/* @__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: [
|
|
2264
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2265
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2266
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "text-lg font-bold text-white", children: "Upgrade Required" }),
|
|
2267
|
-
/* @__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" })
|
|
2268
|
-
] }),
|
|
2269
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2270
|
-
ClayxButton,
|
|
2271
|
-
{
|
|
2272
|
-
onClick: closeToast,
|
|
2273
|
-
isIconOnly: true,
|
|
2274
|
-
size: "sm",
|
|
2275
|
-
onMouseEnter: () => setCloseHover(true),
|
|
2276
|
-
onMouseLeave: () => setCloseHover(false),
|
|
2277
|
-
style: {
|
|
2278
|
-
height: "1.5rem",
|
|
2279
|
-
width: "1.5rem",
|
|
2280
|
-
minWidth: "1.5rem",
|
|
2281
|
-
borderRadius: "9999px",
|
|
2282
|
-
backgroundColor: closeHover ? "rgba(255,255,255,0.1)" : "rgba(255,255,255,0.05)",
|
|
2283
|
-
transition: "background-color 150ms ease",
|
|
2284
|
-
cursor: "pointer"
|
|
2285
|
-
},
|
|
2286
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react14.Icon, { icon: "iconamoon:close", className: "w-4 h-4 text-gray-400" })
|
|
2287
|
-
}
|
|
2288
|
-
)
|
|
2289
|
-
] }),
|
|
2290
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-sm text-gray-300 leading-relaxed", children: message }),
|
|
2291
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-1 flex items-center gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2292
|
-
ClayxButton,
|
|
2293
|
-
{
|
|
2294
|
-
onClick: () => {
|
|
2295
|
-
onUpgrade();
|
|
2296
|
-
closeToast?.();
|
|
2297
|
-
},
|
|
2298
|
-
onMouseEnter: () => setHover(true),
|
|
2299
|
-
onMouseLeave: () => setHover(false),
|
|
2300
|
-
style: {
|
|
2301
|
-
flex: 1,
|
|
2302
|
-
color: "#ffffff",
|
|
2303
|
-
fontWeight: 600,
|
|
2304
|
-
cursor: "pointer",
|
|
2305
|
-
transition: "all 300ms ease-in-out",
|
|
2306
|
-
backgroundImage: hover ? "linear-gradient(to right, #9333ea, #db2777)" : "linear-gradient(to right, #a855f7, #ec4899)",
|
|
2307
|
-
boxShadow: hover ? "0 10px 15px -3px rgba(168,85,247,0.3), 0 4px 6px -2px rgba(168,85,247,0.3)" : "none"
|
|
2308
|
-
},
|
|
2309
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "flex items-center gap-2", children: [
|
|
2310
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react14.Icon, { icon: "solar:rocket-2-bold", className: "w-4 h-4" }),
|
|
2311
|
-
"Upgrade Now"
|
|
2312
|
-
] })
|
|
2313
|
-
}
|
|
2314
|
-
) })
|
|
2315
|
-
] }) })
|
|
2316
|
-
] });
|
|
2317
|
-
};
|
|
2318
|
-
function showLimitUpgradeToast(message, onUpgrade) {
|
|
2319
|
-
ClayxToast.default({
|
|
2320
|
-
render: (closeToast) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LimitToastContainer, { message, onUpgrade, closeToast }),
|
|
2321
|
-
options: {
|
|
2322
|
-
autoClose: false
|
|
2323
|
-
}
|
|
2324
|
-
});
|
|
2325
|
-
}
|
|
2326
|
-
|
|
2327
|
-
// src/services/ai-workflow.ts
|
|
2328
|
-
var AIWorkflowClient = class {
|
|
2329
|
-
constructor(options = {}) {
|
|
2330
|
-
this.baseUrl = options.baseUrl?.replace(/\/+$/, "") || "";
|
|
2331
|
-
this.apiKey = options.apiKey;
|
|
2332
|
-
this.headers = { "Content-Type": "application/json", ...options.headers || {} };
|
|
2333
|
-
this.fetchImpl = options.fetchImpl || fetch.bind(globalThis);
|
|
2334
|
-
}
|
|
2335
|
-
buildHeaders(extra) {
|
|
2336
|
-
const h = { ...this.headers, ...extra || {} };
|
|
2337
|
-
if (this.apiKey && !h["Authorization"]) {
|
|
2338
|
-
h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
2339
|
-
}
|
|
2340
|
-
return h;
|
|
2341
|
-
}
|
|
2342
|
-
async safeJson(resp) {
|
|
2343
|
-
try {
|
|
2344
|
-
return await resp.json();
|
|
2345
|
-
} catch (_e) {
|
|
2346
|
-
return null;
|
|
2347
|
-
}
|
|
2348
|
-
}
|
|
2349
|
-
/**
|
|
2350
|
-
* 按 ID 执行工作流:POST {baseUrl}/workflow/{workflowId}/execute
|
|
2351
|
-
* body: { input, options }
|
|
2352
|
-
*/
|
|
2353
|
-
async executeWorkflow(workflowId, inputs, options) {
|
|
2354
|
-
if (!this.baseUrl) {
|
|
2355
|
-
throw new Error("AI workflow client requires a baseUrl (e.g. https://evoagentx-server.fly.dev)");
|
|
2356
|
-
}
|
|
2357
|
-
const url = `${this.baseUrl}/workflow/${workflowId}/execute`;
|
|
2358
|
-
try {
|
|
2359
|
-
const res = await this.fetchImpl(url, {
|
|
2360
|
-
method: "POST",
|
|
2361
|
-
headers: this.buildHeaders(),
|
|
2362
|
-
body: JSON.stringify({ inputs, options })
|
|
2363
|
-
});
|
|
2364
|
-
const data = await this.safeJson(res);
|
|
2365
|
-
if (!res.ok) {
|
|
2366
|
-
return { success: false, error: data?.error || `HTTP ${res.status}` };
|
|
2367
|
-
}
|
|
2368
|
-
if (data && data.status && data.status === 4003) {
|
|
2369
|
-
showLimitUpgradeToast(
|
|
2370
|
-
"Your credits are exhausted. Please upgrade your plan to continue generating projects.",
|
|
2371
|
-
() => window.open("https://clayx.ai/pricing", "_blank")
|
|
2372
|
-
);
|
|
2373
|
-
return null;
|
|
2374
|
-
}
|
|
2375
|
-
return data || { success: true };
|
|
2376
|
-
} catch (error) {
|
|
2377
|
-
return { success: false, error: error instanceof Error ? error.message : "Network error" };
|
|
2378
|
-
}
|
|
2379
|
-
}
|
|
2380
|
-
};
|
|
2381
|
-
function createAIWorkflowClient(options = {}) {
|
|
2382
|
-
return new AIWorkflowClient(options);
|
|
2383
|
-
}
|
|
2384
|
-
var aiWorkflow = createAIWorkflowClient({ baseUrl: "https://evoagentx-server" });
|
|
2385
|
-
|
|
2386
|
-
// src/services/request/index.ts
|
|
2387
|
-
var import_axios = __toESM(require("axios"));
|
|
2388
|
-
var Request = class {
|
|
2389
|
-
constructor(config) {
|
|
2390
|
-
this.abortControllers = /* @__PURE__ */ new Map();
|
|
2391
|
-
this.instance = import_axios.default.create({
|
|
2392
|
-
...config,
|
|
2393
|
-
withCredentials: true,
|
|
2394
|
-
validateStatus: (status) => {
|
|
2395
|
-
return status >= 200 && status < 300;
|
|
2396
|
-
}
|
|
2397
|
-
});
|
|
2398
|
-
this.interceptors = config.interceptors;
|
|
2399
|
-
this.instance.interceptors.request.use(
|
|
2400
|
-
this.interceptors?.requestInterceptor,
|
|
2401
|
-
this.interceptors?.requestInterceptorCatch
|
|
2402
|
-
);
|
|
2403
|
-
this.instance.interceptors.response.use(
|
|
2404
|
-
this.interceptors?.responseInterceptor,
|
|
2405
|
-
this.interceptors?.responseInterceptorCatch
|
|
2406
|
-
);
|
|
2407
|
-
this.instance.interceptors.request.use(
|
|
2408
|
-
(config2) => {
|
|
2409
|
-
return config2;
|
|
2410
|
-
},
|
|
2411
|
-
(err) => {
|
|
2412
|
-
return Promise.reject(err);
|
|
2413
|
-
}
|
|
2414
|
-
);
|
|
2415
|
-
this.instance.interceptors.response.use(
|
|
2416
|
-
(res) => {
|
|
2417
|
-
return res.data;
|
|
2418
|
-
},
|
|
2419
|
-
(err) => {
|
|
2420
|
-
if (import_axios.default.isCancel(err)) {
|
|
2421
|
-
return Promise.reject({
|
|
2422
|
-
isCanceled: true,
|
|
2423
|
-
message: "request canceled",
|
|
2424
|
-
originalError: err
|
|
2425
|
-
});
|
|
2426
|
-
}
|
|
2427
|
-
if (err.response?.data?.error) {
|
|
2428
|
-
return Promise.reject(err.response.data.error);
|
|
2429
|
-
}
|
|
2430
|
-
return Promise.reject(err);
|
|
2431
|
-
}
|
|
2432
|
-
);
|
|
2433
|
-
}
|
|
2434
|
-
cancelRequest(url) {
|
|
2435
|
-
this.abortControllers.forEach((controller, key) => {
|
|
2436
|
-
if (key.includes(url)) {
|
|
2437
|
-
controller.abort();
|
|
2438
|
-
this.abortControllers.delete(key);
|
|
2439
|
-
}
|
|
2440
|
-
});
|
|
2441
|
-
}
|
|
2442
|
-
cancelAllRequests() {
|
|
2443
|
-
this.abortControllers.forEach((controller) => {
|
|
2444
|
-
controller.abort();
|
|
2445
|
-
});
|
|
2446
|
-
this.abortControllers.clear();
|
|
2447
|
-
}
|
|
2448
|
-
request(config) {
|
|
2449
|
-
const controller = new AbortController();
|
|
2450
|
-
const url = config.url || "";
|
|
2451
|
-
const method = config.method || "GET";
|
|
2452
|
-
const key = `${method}:${url}`;
|
|
2453
|
-
this.abortControllers.set(key, controller);
|
|
2454
|
-
config.signal = controller.signal;
|
|
2455
|
-
return new Promise((resolve, reject) => {
|
|
2456
|
-
if (config.interceptors?.requestInterceptor) {
|
|
2457
|
-
config = config.interceptors.requestInterceptor(config);
|
|
2458
|
-
}
|
|
2459
|
-
this.instance.request(config).then((res) => {
|
|
2460
|
-
this.abortControllers.delete(key);
|
|
2461
|
-
if (config.interceptors?.responseInterceptor) {
|
|
2462
|
-
res = config.interceptors.responseInterceptor(res);
|
|
2463
|
-
}
|
|
2464
|
-
resolve(res);
|
|
2465
|
-
}).catch((err) => {
|
|
2466
|
-
this.abortControllers.delete(key);
|
|
2467
|
-
reject(err);
|
|
2468
|
-
});
|
|
2469
|
-
});
|
|
2470
|
-
}
|
|
2471
|
-
get(config) {
|
|
2472
|
-
return this.request({ ...config, method: "GET" });
|
|
2473
|
-
}
|
|
2474
|
-
post(config) {
|
|
2475
|
-
return this.request({ ...config, method: "POST" });
|
|
2476
|
-
}
|
|
2477
|
-
delete(config) {
|
|
2478
|
-
return this.request({ ...config, method: "DELETE" });
|
|
2479
|
-
}
|
|
2480
|
-
put(config) {
|
|
2481
|
-
return this.request({ ...config, method: "PUT" });
|
|
2482
|
-
}
|
|
2483
|
-
patch(config) {
|
|
2484
|
-
return this.request({ ...config, method: "PATCH" });
|
|
2485
|
-
}
|
|
2486
|
-
};
|
|
2487
|
-
var request_default = Request;
|
|
2488
|
-
|
|
2489
|
-
// src/services/ai-workflow-axios.ts
|
|
2490
|
-
function createAIWorkflowClientAxios(options = {}) {
|
|
2491
|
-
const basePath = options.basePath ?? "/api";
|
|
2492
|
-
const baseUrl = (options.baseUrl || "https://evoagentx-server.fly.dev").replace(/\/+$/, "");
|
|
2493
|
-
const baseAPI = `${baseUrl}${basePath.startsWith("/") ? "" : "/"}${basePath}`.replace(/\/+$/, "");
|
|
2494
|
-
const client = options.requestInstance || new request_default({
|
|
2495
|
-
baseURL: baseAPI,
|
|
2496
|
-
timeout: options.timeout ?? 6e4,
|
|
2497
|
-
interceptors: {
|
|
2498
|
-
requestInterceptor: (config) => {
|
|
2499
|
-
config.headers = config.headers || {};
|
|
2500
|
-
if (options.apiKey && !config.headers["Authorization"]) {
|
|
2501
|
-
config.headers["Authorization"] = `Bearer ${options.apiKey}`;
|
|
2609
|
+
maskComposite: "exclude"
|
|
2502
2610
|
}
|
|
2503
|
-
|
|
2504
|
-
|
|
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
|
+
] })
|
|
2505
2665
|
}
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
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
|
|
2511
2675
|
}
|
|
2512
2676
|
});
|
|
2513
|
-
return {
|
|
2514
|
-
async executeWorkflow(workflowId, inputs, opts) {
|
|
2515
|
-
const url = `${baseUrl}/workflow/${workflowId}/execute`;
|
|
2516
|
-
const data = await client.post({ url, data: { inputs, options: opts } });
|
|
2517
|
-
return data;
|
|
2518
|
-
}
|
|
2519
|
-
};
|
|
2520
2677
|
}
|
|
2521
2678
|
|
|
2522
|
-
// src/services/
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
return false;
|
|
2530
|
-
}
|
|
2531
|
-
if (a.visibility === "private") {
|
|
2532
|
-
if (ctx.userId && a.ownerId && ctx.userId === a.ownerId) return true;
|
|
2533
|
-
if (ctx.tokenScopes && (ctx.tokenScopes.includes("artifact:read:all") || ctx.tokenScopes.includes("admin"))) return true;
|
|
2534
|
-
return false;
|
|
2535
|
-
}
|
|
2536
|
-
if (a.visibility === "shared") {
|
|
2537
|
-
if (ctx.userId && a.sharedWith && a.sharedWith.includes(ctx.userId)) return true;
|
|
2538
|
-
if (ctx.tokenScopes && (ctx.tokenScopes.includes("artifact:read:all") || ctx.tokenScopes.includes("admin"))) return true;
|
|
2539
|
-
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;
|
|
2540
2686
|
}
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
return {
|
|
2547
|
-
async create(input) {
|
|
2548
|
-
return await req.post({ url: "/artifacts", data: input });
|
|
2549
|
-
},
|
|
2550
|
-
async list(query) {
|
|
2551
|
-
return await req.get({ url: "/artifacts", params: query });
|
|
2552
|
-
},
|
|
2553
|
-
async get(id) {
|
|
2554
|
-
return await req.get({ url: `/artifacts/${encodeURIComponent(id)}` });
|
|
2555
|
-
},
|
|
2556
|
-
async setVisibility(id, visibility) {
|
|
2557
|
-
await req.patch({ url: `/artifacts/${encodeURIComponent(id)}/visibility`, data: { visibility } });
|
|
2558
|
-
},
|
|
2559
|
-
async delete(id) {
|
|
2560
|
-
await req.delete({ url: `/artifacts/${encodeURIComponent(id)}` });
|
|
2561
|
-
},
|
|
2562
|
-
// convenience local check (server is authoritative)
|
|
2563
|
-
canAccessLocal(a, ctx) {
|
|
2564
|
-
if (!a) return false;
|
|
2565
|
-
if (a.visibility === "public") return true;
|
|
2566
|
-
if (a.visibility === "project") return Boolean(ctx.projectId && a.projectId && ctx.projectId === a.projectId);
|
|
2567
|
-
if (a.visibility === "private") return Boolean(ctx.userId && a.ownerId && ctx.userId === a.ownerId);
|
|
2568
|
-
if (a.visibility === "shared") return Boolean(ctx.userId && a.sharedWith && a.sharedWith.includes(ctx.userId));
|
|
2569
|
-
return false;
|
|
2570
|
-
}
|
|
2571
|
-
};
|
|
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
|
+
);
|
|
2572
2692
|
}
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2693
|
+
function mergeLimitExceededOptions(base, override) {
|
|
2694
|
+
if (!base && !override) {
|
|
2695
|
+
return void 0;
|
|
2696
|
+
}
|
|
2577
2697
|
return {
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
* @example
|
|
2582
|
-
* ```typescript
|
|
2583
|
-
* const { url } = await client.upload.file(imageFile)
|
|
2584
|
-
* console.log('文件地址:', url)
|
|
2585
|
-
* ```
|
|
2586
|
-
*/
|
|
2587
|
-
async file(file, options) {
|
|
2588
|
-
const formData = new FormData();
|
|
2589
|
-
if (typeof file === "string") {
|
|
2590
|
-
if (file.startsWith("data:")) {
|
|
2591
|
-
const response2 = await fetch(file);
|
|
2592
|
-
const blob = await response2.blob();
|
|
2593
|
-
formData.append("file", blob, "upload.bin");
|
|
2594
|
-
} else {
|
|
2595
|
-
formData.append("fileUrl", file);
|
|
2596
|
-
}
|
|
2597
|
-
} else if (file instanceof File) {
|
|
2598
|
-
formData.append("file", file, file.name);
|
|
2599
|
-
} else {
|
|
2600
|
-
formData.append("file", file, "upload.bin");
|
|
2601
|
-
}
|
|
2602
|
-
if (options?.metadata) {
|
|
2603
|
-
formData.append("metadata", JSON.stringify(options.metadata));
|
|
2604
|
-
}
|
|
2605
|
-
const response = await req.post({
|
|
2606
|
-
url: uploadUrl,
|
|
2607
|
-
data: formData,
|
|
2608
|
-
signal: options?.signal
|
|
2609
|
-
});
|
|
2610
|
-
return {
|
|
2611
|
-
url: response.data.publicUrl
|
|
2612
|
-
};
|
|
2613
|
-
},
|
|
2614
|
-
/**
|
|
2615
|
-
* 上传图片(快捷方法,专为 AI 设计)
|
|
2616
|
-
*
|
|
2617
|
-
* @example
|
|
2618
|
-
* ```typescript
|
|
2619
|
-
* const { url } = await client.upload.image(imageFile)
|
|
2620
|
-
* ```
|
|
2621
|
-
*/
|
|
2622
|
-
async image(file) {
|
|
2623
|
-
const result = await this.file(file);
|
|
2624
|
-
return { url: result.url };
|
|
2625
|
-
},
|
|
2626
|
-
/**
|
|
2627
|
-
* 批量上传文件
|
|
2628
|
-
*
|
|
2629
|
-
* @example
|
|
2630
|
-
* ```typescript
|
|
2631
|
-
* const result = await client.upload.batch({
|
|
2632
|
-
* files: [file1, file2, file3],
|
|
2633
|
-
* concurrent: 3,
|
|
2634
|
-
* onProgress: (completed, total) => {
|
|
2635
|
-
* console.log(`${completed}/${total}`)
|
|
2636
|
-
* }
|
|
2637
|
-
* })
|
|
2638
|
-
* ```
|
|
2639
|
-
*/
|
|
2640
|
-
async batch(options) {
|
|
2641
|
-
const { files, concurrent = 3, onProgress, onFileComplete, signal } = options;
|
|
2642
|
-
const success = [];
|
|
2643
|
-
const failed = [];
|
|
2644
|
-
let completed = 0;
|
|
2645
|
-
for (let i = 0; i < files.length; i += concurrent) {
|
|
2646
|
-
if (signal?.aborted) break;
|
|
2647
|
-
const batch = files.slice(i, Math.min(i + concurrent, files.length));
|
|
2648
|
-
const promises = batch.map(async (file, batchIndex) => {
|
|
2649
|
-
const globalIndex = i + batchIndex;
|
|
2650
|
-
try {
|
|
2651
|
-
const result = await this.file(file, { signal });
|
|
2652
|
-
success.push(result);
|
|
2653
|
-
if (onFileComplete) {
|
|
2654
|
-
onFileComplete(result, globalIndex);
|
|
2655
|
-
}
|
|
2656
|
-
} catch (error) {
|
|
2657
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2658
|
-
failed.push({ index: globalIndex, error: errorMsg });
|
|
2659
|
-
if (onFileComplete) {
|
|
2660
|
-
onFileComplete(
|
|
2661
|
-
error instanceof Error ? error : new Error(errorMsg),
|
|
2662
|
-
globalIndex
|
|
2663
|
-
);
|
|
2664
|
-
}
|
|
2665
|
-
} finally {
|
|
2666
|
-
completed++;
|
|
2667
|
-
if (onProgress) {
|
|
2668
|
-
onProgress(completed, files.length);
|
|
2669
|
-
}
|
|
2670
|
-
}
|
|
2671
|
-
});
|
|
2672
|
-
await Promise.all(promises);
|
|
2673
|
-
}
|
|
2674
|
-
return {
|
|
2675
|
-
success,
|
|
2676
|
-
failed,
|
|
2677
|
-
total: files.length
|
|
2678
|
-
};
|
|
2679
|
-
}
|
|
2698
|
+
...base,
|
|
2699
|
+
...override,
|
|
2700
|
+
onLimitExceeded: override?.onLimitExceeded ?? base?.onLimitExceeded
|
|
2680
2701
|
};
|
|
2681
2702
|
}
|
|
2682
2703
|
|
|
2683
2704
|
// src/services/sse-executor.ts
|
|
2684
|
-
init_config();
|
|
2685
2705
|
async function executeSSEWorkflow(request, options = {}) {
|
|
2686
2706
|
const startTime = Date.now();
|
|
2687
2707
|
const result = {
|
|
@@ -2782,11 +2802,16 @@ async function executeSSEWorkflow(request, options = {}) {
|
|
|
2782
2802
|
options.onStreamContent(rawEvent.delta);
|
|
2783
2803
|
}
|
|
2784
2804
|
if (rawEvent.type === "key_limit_exceed") {
|
|
2785
|
-
const errorMsg = rawEvent.data
|
|
2805
|
+
const errorMsg = rawEvent.data?.content || DEFAULT_LIMIT_EXCEEDED_MESSAGE;
|
|
2786
2806
|
result.errors.push(errorMsg);
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2807
|
+
handleLimitExceeded(
|
|
2808
|
+
{
|
|
2809
|
+
source: "sse-executor",
|
|
2810
|
+
message: errorMsg,
|
|
2811
|
+
eventType: rawEvent.type,
|
|
2812
|
+
rawData: rawEvent.data
|
|
2813
|
+
},
|
|
2814
|
+
options.limitExceeded
|
|
2790
2815
|
);
|
|
2791
2816
|
if (options.onError) {
|
|
2792
2817
|
options.onError(new Error(errorMsg));
|
|
@@ -2997,7 +3022,7 @@ function createEventIterable(streamFactory, config) {
|
|
|
2997
3022
|
};
|
|
2998
3023
|
}
|
|
2999
3024
|
function createSSEClient(config) {
|
|
3000
|
-
const { baseUrl, projectId, getAuthToken } = config;
|
|
3025
|
+
const { baseUrl, projectId, getAuthToken, limitExceeded } = config;
|
|
3001
3026
|
const stream = (streamConfig) => {
|
|
3002
3027
|
const { signal: externalSignal, ...callbacks } = streamConfig;
|
|
3003
3028
|
const request = resolveRequest(baseUrl, projectId, streamConfig);
|
|
@@ -3013,7 +3038,11 @@ function createSSEClient(config) {
|
|
|
3013
3038
|
{
|
|
3014
3039
|
...callbacks,
|
|
3015
3040
|
authToken,
|
|
3016
|
-
signal: controller.signal
|
|
3041
|
+
signal: controller.signal,
|
|
3042
|
+
limitExceeded: mergeLimitExceededOptions(
|
|
3043
|
+
limitExceeded,
|
|
3044
|
+
streamConfig.limitExceeded
|
|
3045
|
+
)
|
|
3017
3046
|
}
|
|
3018
3047
|
).finally(() => {
|
|
3019
3048
|
controller.cleanup();
|
|
@@ -3189,6 +3218,19 @@ async function executeWorkflowStreamPost(baseUrl, projectId, workflowId, request
|
|
|
3189
3218
|
break;
|
|
3190
3219
|
case "error":
|
|
3191
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
|
+
}
|
|
3192
3234
|
}
|
|
3193
3235
|
} catch (err) {
|
|
3194
3236
|
console.error("Failed to parse SSE event:", err);
|
|
@@ -3207,12 +3249,12 @@ async function executeWorkflowStreamPost(baseUrl, projectId, workflowId, request
|
|
|
3207
3249
|
}
|
|
3208
3250
|
|
|
3209
3251
|
// src/services/workflow-executor.ts
|
|
3210
|
-
init_config();
|
|
3211
3252
|
var WorkflowExecutor = class {
|
|
3212
|
-
constructor(baseUrl, projectId, authToken) {
|
|
3253
|
+
constructor(baseUrl, projectId, authToken, limitExceeded) {
|
|
3213
3254
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
3214
3255
|
this.projectId = projectId;
|
|
3215
3256
|
this.authToken = authToken;
|
|
3257
|
+
this.limitExceeded = limitExceeded;
|
|
3216
3258
|
}
|
|
3217
3259
|
/**
|
|
3218
3260
|
* 执行工作流 (SSE 模式)
|
|
@@ -3262,6 +3304,10 @@ var WorkflowExecutor = class {
|
|
|
3262
3304
|
errors: []
|
|
3263
3305
|
};
|
|
3264
3306
|
let streamContent = "";
|
|
3307
|
+
const limitExceededOptions = mergeLimitExceededOptions(
|
|
3308
|
+
this.limitExceeded,
|
|
3309
|
+
options?.limitExceeded
|
|
3310
|
+
);
|
|
3265
3311
|
try {
|
|
3266
3312
|
const response = await fetch(url, {
|
|
3267
3313
|
method: "POST",
|
|
@@ -3314,11 +3360,16 @@ var WorkflowExecutor = class {
|
|
|
3314
3360
|
}
|
|
3315
3361
|
}
|
|
3316
3362
|
} else if (event.type === "key_limit_exceed") {
|
|
3317
|
-
const errorMsg = event.data?.content;
|
|
3363
|
+
const errorMsg = event.data?.content || DEFAULT_LIMIT_EXCEEDED_MESSAGE;
|
|
3318
3364
|
result.errors.push(errorMsg);
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3365
|
+
handleLimitExceeded(
|
|
3366
|
+
{
|
|
3367
|
+
source: "workflow-executor-sse",
|
|
3368
|
+
message: errorMsg,
|
|
3369
|
+
eventType: event.type,
|
|
3370
|
+
rawData: event.data
|
|
3371
|
+
},
|
|
3372
|
+
limitExceededOptions
|
|
3322
3373
|
);
|
|
3323
3374
|
if (options?.onError) {
|
|
3324
3375
|
options.onError(new Error(errorMsg));
|
|
@@ -3402,6 +3453,17 @@ var WorkflowExecutor = class {
|
|
|
3402
3453
|
body: JSON.stringify({ inputs })
|
|
3403
3454
|
});
|
|
3404
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
|
+
}
|
|
3405
3467
|
return {
|
|
3406
3468
|
status: response.status,
|
|
3407
3469
|
data
|
|
@@ -3483,14 +3545,6 @@ function createClient(opts) {
|
|
|
3483
3545
|
},
|
|
3484
3546
|
requestInterceptorCatch: (err) => Promise.reject(err),
|
|
3485
3547
|
responseInterceptor: (res) => {
|
|
3486
|
-
const data = res.data;
|
|
3487
|
-
if (data && data.status && data.status === 4003) {
|
|
3488
|
-
showLimitUpgradeToast(
|
|
3489
|
-
"Your credits are exhausted. Please upgrade your plan to continue generating projects.",
|
|
3490
|
-
() => window.open(`${getEnvs().AUTH_ROOT_VALUE}/price`, "_blank")
|
|
3491
|
-
);
|
|
3492
|
-
return res;
|
|
3493
|
-
}
|
|
3494
3548
|
return res;
|
|
3495
3549
|
},
|
|
3496
3550
|
responseInterceptorCatch: (err) => Promise.reject(err)
|
|
@@ -3598,7 +3652,8 @@ function createClient(opts) {
|
|
|
3598
3652
|
void fetchExternalToken();
|
|
3599
3653
|
}
|
|
3600
3654
|
return token ?? cachedExternalToken ?? getToken() ?? null;
|
|
3601
|
-
}
|
|
3655
|
+
},
|
|
3656
|
+
limitExceeded: opts.limitExceeded
|
|
3602
3657
|
});
|
|
3603
3658
|
const assignMethod = (config, method) => method ? { ...config, method } : config;
|
|
3604
3659
|
function createMethodInvoker(invoker) {
|
|
@@ -3649,7 +3704,13 @@ function createClient(opts) {
|
|
|
3649
3704
|
opts.projectId,
|
|
3650
3705
|
workflowId,
|
|
3651
3706
|
{ inputs },
|
|
3652
|
-
|
|
3707
|
+
{
|
|
3708
|
+
...streamOptions,
|
|
3709
|
+
limitExceeded: mergeLimitExceededOptions(
|
|
3710
|
+
opts.limitExceeded,
|
|
3711
|
+
streamOptions?.limitExceeded
|
|
3712
|
+
)
|
|
3713
|
+
},
|
|
3653
3714
|
authToken || void 0
|
|
3654
3715
|
);
|
|
3655
3716
|
};
|
|
@@ -3660,7 +3721,8 @@ function createClient(opts) {
|
|
|
3660
3721
|
const executor = new WorkflowExecutor(
|
|
3661
3722
|
actualAiBaseUrl,
|
|
3662
3723
|
opts.projectId,
|
|
3663
|
-
getCachedOrGlobalToken() ?? void 0
|
|
3724
|
+
getCachedOrGlobalToken() ?? void 0,
|
|
3725
|
+
opts.limitExceeded
|
|
3664
3726
|
);
|
|
3665
3727
|
return {
|
|
3666
3728
|
executeSse: (inputs, options) => {
|
|
@@ -4291,6 +4353,7 @@ var elementSelector = {
|
|
|
4291
4353
|
AUTH_TOKEN_KEY,
|
|
4292
4354
|
ClayxButton,
|
|
4293
4355
|
ClayxToast,
|
|
4356
|
+
DEFAULT_LIMIT_EXCEEDED_MESSAGE,
|
|
4294
4357
|
DefaultErrorFallback,
|
|
4295
4358
|
ElementSelector,
|
|
4296
4359
|
ElementSelectorProvider,
|
|
@@ -4320,11 +4383,13 @@ var elementSelector = {
|
|
|
4320
4383
|
getEnvs,
|
|
4321
4384
|
getGlobalEnvironment,
|
|
4322
4385
|
getToken,
|
|
4386
|
+
handleLimitExceeded,
|
|
4323
4387
|
howone,
|
|
4324
4388
|
iframeNavigation,
|
|
4325
4389
|
initIframeNavigation,
|
|
4326
4390
|
isTokenValid,
|
|
4327
4391
|
loginWithEmailCode,
|
|
4392
|
+
mergeLimitExceededOptions,
|
|
4328
4393
|
onAuthStateChanged,
|
|
4329
4394
|
parseUserFromToken,
|
|
4330
4395
|
sendElementSelectionToParent,
|