@howone/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,1438 @@
1
+ // src/components/FloatingButton.tsx
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ var FloatingButton = ({
4
+ text = "Made in Howone",
5
+ onClick,
6
+ className = ""
7
+ }) => {
8
+ return /* @__PURE__ */ jsxs(
9
+ "button",
10
+ {
11
+ onClick,
12
+ className: `fixed flex bg-white gap-2 items-center right-4 z-50 text-black px-3 py-2 rounded-lg shadow-lg transition-colors duration-200 ${className}`,
13
+ style: {
14
+ fontSize: "14px",
15
+ fontWeight: "bold",
16
+ bottom: "28px"
17
+ },
18
+ children: [
19
+ /* @__PURE__ */ jsx("img", { width: 20, src: "https://sxwxqoixnnklnpeutjrj.supabase.co/storage/v1/object/public/create-x/logo/logo-sm.svg", alt: "" }),
20
+ text
21
+ ]
22
+ }
23
+ );
24
+ };
25
+
26
+ // src/services/unified-oauth.ts
27
+ var UnifiedAuthService = class {
28
+ constructor() {
29
+ this.API_BASE_URL = "https://create-x-backend.fly.dev";
30
+ }
31
+ /**
32
+ * 初始化 Google 登录流程
33
+ * @returns 包含 token 和用户信息的 Promise
34
+ */
35
+ async initiateGoogleLogin() {
36
+ const currentUrl = window.location.href;
37
+ const state = {
38
+ from_url: currentUrl,
39
+ app_id: this.generateAppId(),
40
+ timestamp: Date.now()
41
+ };
42
+ const stateString = encodeURIComponent(JSON.stringify(state));
43
+ try {
44
+ const response = await fetch(`${this.API_BASE_URL}/api/auth/google?state=${stateString}`);
45
+ const data = await response.json();
46
+ if (!data.data.success || !data.data.authUrl) {
47
+ throw new Error("Failed to get OAuth URL");
48
+ }
49
+ return this.openOAuthPopup(data.data.authUrl);
50
+ } catch (error) {
51
+ throw error;
52
+ }
53
+ }
54
+ /**
55
+ * 打开 OAuth 认证弹窗
56
+ * @param authUrl 认证 URL
57
+ * @returns 包含 token 和用户信息的 Promise
58
+ */
59
+ openOAuthPopup(authUrl) {
60
+ return new Promise((resolve, reject) => {
61
+ const width = 500;
62
+ const height = 600;
63
+ const left = window.screen.width / 2 - width / 2;
64
+ const top = window.screen.height / 2 - height / 2;
65
+ const popup = window.open(
66
+ authUrl,
67
+ "oauth-popup",
68
+ `width=${width},height=${height},left=${left},top=${top},scrollbars=yes,resizable=yes`
69
+ );
70
+ if (!popup) {
71
+ reject(new Error("Unable to open popup, please check browser popup settings"));
72
+ return;
73
+ }
74
+ let popupClosed = false;
75
+ let popupCheckInterval = null;
76
+ const checkPopupStatus = () => {
77
+ try {
78
+ if (!popup || popup.closed) {
79
+ if (!popupClosed) {
80
+ popupClosed = true;
81
+ if (popupCheckInterval) {
82
+ clearInterval(popupCheckInterval);
83
+ popupCheckInterval = null;
84
+ }
85
+ window.removeEventListener("message", messageHandler);
86
+ reject(new Error("User cancelled login"));
87
+ }
88
+ }
89
+ } catch (e) {
90
+ if (!popupClosed) {
91
+ popupClosed = true;
92
+ if (popupCheckInterval) {
93
+ clearInterval(popupCheckInterval);
94
+ popupCheckInterval = null;
95
+ }
96
+ window.removeEventListener("message", messageHandler);
97
+ reject(new Error("User cancelled login"));
98
+ }
99
+ }
100
+ };
101
+ popupCheckInterval = window.setInterval(checkPopupStatus, 1e3);
102
+ const messageHandler = (event) => {
103
+ const validOrigins = [
104
+ window.location.origin,
105
+ "https://create-x-backend.fly.dev"
106
+ ];
107
+ const isValidOrigin = validOrigins.some(
108
+ (origin) => event.origin === origin || event.origin.includes("localhost") || event.origin.includes("127.0.0.1") || event.origin.includes("fly.dev")
109
+ );
110
+ if (!isValidOrigin) {
111
+ return;
112
+ }
113
+ if (event.data && event.data.type === "OAUTH_SUCCESS") {
114
+ popupClosed = true;
115
+ if (popupCheckInterval) {
116
+ clearInterval(popupCheckInterval);
117
+ popupCheckInterval = null;
118
+ }
119
+ window.removeEventListener("message", messageHandler);
120
+ try {
121
+ if (popup) popup.close();
122
+ } catch (e) {
123
+ }
124
+ resolve(event.data.payload);
125
+ } else if (event.data && event.data.type === "OAUTH_ERROR") {
126
+ popupClosed = true;
127
+ if (popupCheckInterval) {
128
+ clearInterval(popupCheckInterval);
129
+ popupCheckInterval = null;
130
+ }
131
+ window.removeEventListener("message", messageHandler);
132
+ try {
133
+ if (popup) popup.close();
134
+ } catch (e) {
135
+ }
136
+ reject(new Error(event.data.error || "login failed"));
137
+ }
138
+ };
139
+ window.addEventListener("message", messageHandler);
140
+ setTimeout(() => {
141
+ if (!popupClosed) {
142
+ popupClosed = true;
143
+ if (popupCheckInterval) {
144
+ clearInterval(popupCheckInterval);
145
+ popupCheckInterval = null;
146
+ }
147
+ window.removeEventListener("message", messageHandler);
148
+ try {
149
+ if (popup) popup.close();
150
+ } catch (e) {
151
+ }
152
+ reject(new Error("login timeout"));
153
+ }
154
+ }, 5 * 60 * 1e3);
155
+ });
156
+ }
157
+ /**
158
+ * 初始化 GitHub 登录流程
159
+ * @returns 包含 token 和用户信息的 Promise
160
+ */
161
+ async initiateGitHubLogin() {
162
+ const currentUrl = window.location.href;
163
+ const state = {
164
+ from_url: currentUrl,
165
+ app_id: this.generateAppId(),
166
+ timestamp: Date.now()
167
+ };
168
+ const stateString = encodeURIComponent(JSON.stringify(state));
169
+ try {
170
+ const response = await fetch(`${this.API_BASE_URL}/api/auth/github?state=${stateString}`);
171
+ const data = await response.json();
172
+ if (!data.data.success || !data.data.authUrl) {
173
+ throw new Error("Failed to get GitHub OAuth URL");
174
+ }
175
+ return this.openOAuthPopup(data.data.authUrl);
176
+ } catch (error) {
177
+ throw error;
178
+ }
179
+ }
180
+ /**
181
+ * 发送邮箱验证码
182
+ * @param email 邮箱地址
183
+ * @param appName 应用名称(可选)
184
+ * @returns 发送结果 Promise
185
+ */
186
+ async sendEmailVerificationCode(email, appName) {
187
+ try {
188
+ const currentUrl = window.location.origin;
189
+ const appId = this.generateAppId();
190
+ const response = await fetch(`${this.API_BASE_URL}/api/auth/email/send-code`, {
191
+ method: "POST",
192
+ headers: {
193
+ "Content-Type": "application/json"
194
+ },
195
+ body: JSON.stringify({
196
+ email,
197
+ from_url: currentUrl,
198
+ app_id: appId,
199
+ app_name: appName
200
+ })
201
+ });
202
+ const data = await response.json();
203
+ if (!response.ok) {
204
+ throw new Error(JSON.stringify(data));
205
+ }
206
+ if (data.code === 0 && data.data && data.data.success === false) {
207
+ throw new Error(JSON.stringify(data));
208
+ }
209
+ if (data.code === 429) {
210
+ throw new Error(JSON.stringify(data));
211
+ }
212
+ return data;
213
+ } catch (error) {
214
+ if (error instanceof Error && error.message.startsWith("{")) {
215
+ throw error;
216
+ }
217
+ throw new Error(error instanceof Error ? error.message : "\u7F51\u7EDC\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5");
218
+ }
219
+ }
220
+ /**
221
+ * 邮箱验证码登录
222
+ * @param email 邮箱地址
223
+ * @param code 验证码
224
+ * @returns 登录结果 Promise
225
+ */
226
+ async loginWithEmailCode(email, code) {
227
+ try {
228
+ const currentUrl = window.location.origin;
229
+ const appId = this.generateAppId();
230
+ const response = await fetch(`${this.API_BASE_URL}/api/auth/email/login`, {
231
+ method: "POST",
232
+ headers: {
233
+ "Content-Type": "application/json"
234
+ },
235
+ body: JSON.stringify({
236
+ email,
237
+ code,
238
+ from_url: currentUrl,
239
+ app_id: appId
240
+ })
241
+ });
242
+ const data = await response.json();
243
+ if (!response.ok) {
244
+ throw new Error(JSON.stringify(data));
245
+ }
246
+ if (data.code === 0 && data.data && data.data.success === false) {
247
+ throw new Error(JSON.stringify(data));
248
+ }
249
+ return data;
250
+ } catch (error) {
251
+ if (error instanceof Error && error.message.startsWith("{")) {
252
+ throw error;
253
+ }
254
+ throw new Error(error instanceof Error ? error.message : "\u7F51\u7EDC\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5");
255
+ }
256
+ }
257
+ /**
258
+ * 获取验证码状态(调试用)
259
+ * @param email 邮箱地址
260
+ * @returns 验证码状态 Promise
261
+ */
262
+ async getCodeStatus(email) {
263
+ try {
264
+ const response = await fetch(
265
+ `${this.API_BASE_URL}/api/auth/email/code-status?email=${encodeURIComponent(email)}`
266
+ );
267
+ return await response.json();
268
+ } catch (error) {
269
+ return { success: false, error: error instanceof Error ? error.message : "\u7F51\u7EDC\u9519\u8BEF" };
270
+ }
271
+ }
272
+ generateAppId() {
273
+ const urlParams = new URLSearchParams(window.location.search);
274
+ let appId = urlParams.get("appId");
275
+ return appId || "app";
276
+ }
277
+ /**
278
+ * 检查 OAuth 回调
279
+ * 从 URL 参数中获取 token 和错误信息
280
+ * @returns 包含 token、用户信息和错误的对象
281
+ */
282
+ checkOAuthCallback() {
283
+ const urlParams = new URLSearchParams(window.location.search);
284
+ const token = urlParams.get("token");
285
+ const error = urlParams.get("error");
286
+ const userParam = urlParams.get("user");
287
+ if (token) {
288
+ let user = null;
289
+ if (userParam) {
290
+ try {
291
+ user = JSON.parse(decodeURIComponent(userParam));
292
+ } catch (e) {
293
+ }
294
+ }
295
+ this.saveAuthData(token, user);
296
+ window.history.replaceState({}, document.title, window.location.pathname);
297
+ return { success: true, token, user };
298
+ }
299
+ if (error) {
300
+ window.history.replaceState({}, document.title, window.location.pathname);
301
+ return { success: false, error: decodeURIComponent(error) };
302
+ }
303
+ const savedAuth = this.getSavedAuthData();
304
+ if (savedAuth && savedAuth.token) {
305
+ return { success: true, ...savedAuth };
306
+ }
307
+ return { success: false };
308
+ }
309
+ /**
310
+ * 验证 token 是否有效
311
+ * @param token JWT token
312
+ * @returns 包含有效状态和用户信息的 Promise
313
+ */
314
+ async verifyToken(token) {
315
+ try {
316
+ const response = await fetch(`${this.API_BASE_URL}/api/auth/verify`, {
317
+ method: "GET",
318
+ headers: {
319
+ "Authorization": `Bearer ${token}`
320
+ }
321
+ });
322
+ if (response.ok) {
323
+ const data = await response.json();
324
+ if (data.success) {
325
+ return { valid: true, user: data.user };
326
+ }
327
+ }
328
+ return { valid: false };
329
+ } catch (error) {
330
+ return { valid: false };
331
+ }
332
+ }
333
+ /**
334
+ * 从本地存储获取认证数据
335
+ */
336
+ getSavedAuthData() {
337
+ try {
338
+ const token = localStorage.getItem("auth_token");
339
+ if (!token) return null;
340
+ let user = null;
341
+ const userJson = localStorage.getItem("auth_user");
342
+ if (userJson) {
343
+ try {
344
+ user = JSON.parse(userJson);
345
+ } catch (e) {
346
+ console.error("Failed to parse saved user data:", e);
347
+ }
348
+ }
349
+ return { token, user };
350
+ } catch (e) {
351
+ console.error("Failed to get auth data from localStorage:", e);
352
+ return null;
353
+ }
354
+ }
355
+ /**
356
+ * 保存认证数据到本地存储
357
+ */
358
+ saveAuthData(token, user) {
359
+ try {
360
+ localStorage.setItem("auth_token", token);
361
+ localStorage.setItem("auth_user", JSON.stringify(user || {}));
362
+ } catch (e) {
363
+ console.error("Failed to save auth data to localStorage:", e);
364
+ }
365
+ }
366
+ /**
367
+ * 退出登录
368
+ * @param token JWT token
369
+ */
370
+ async logout(token) {
371
+ try {
372
+ await fetch(`${this.API_BASE_URL}/api/auth/logout`, {
373
+ method: "POST",
374
+ headers: {
375
+ "Authorization": `Bearer ${token}`
376
+ }
377
+ });
378
+ } catch (error) {
379
+ }
380
+ }
381
+ };
382
+ var unifiedAuth = new UnifiedAuthService();
383
+ var unifiedOAuth = unifiedAuth;
384
+ function sendEmailVerificationCode(email, appName) {
385
+ return unifiedAuth.sendEmailVerificationCode(email, appName);
386
+ }
387
+ function loginWithEmailCode(email, code) {
388
+ return unifiedAuth.loginWithEmailCode(email, code);
389
+ }
390
+ function getCodeStatus(email) {
391
+ return unifiedAuth.getCodeStatus(email);
392
+ }
393
+
394
+ // src/services/ai-workflow.ts
395
+ var AIWorkflowClient = class {
396
+ constructor(options = {}) {
397
+ this.baseUrl = options.baseUrl?.replace(/\/+$/, "") || "";
398
+ this.apiKey = options.apiKey;
399
+ this.headers = { "Content-Type": "application/json", ...options.headers || {} };
400
+ this.fetchImpl = options.fetchImpl || fetch.bind(globalThis);
401
+ }
402
+ buildHeaders(extra) {
403
+ const h = { ...this.headers, ...extra || {} };
404
+ if (this.apiKey && !h["Authorization"]) {
405
+ h["Authorization"] = `Bearer ${this.apiKey}`;
406
+ }
407
+ return h;
408
+ }
409
+ async safeJson(resp) {
410
+ try {
411
+ return await resp.json();
412
+ } catch (_e) {
413
+ return null;
414
+ }
415
+ }
416
+ /**
417
+ * 按 ID 执行工作流:POST {baseUrl}/workflow/{workflowId}/execute
418
+ * body: { input, options }
419
+ */
420
+ async executeWorkflow(workflowId, input, options) {
421
+ if (!this.baseUrl) {
422
+ throw new Error("AI workflow client requires a baseUrl (e.g. https://evoagentx-server.fly.dev)");
423
+ }
424
+ const url = `${this.baseUrl}/workflow/${encodeURIComponent(workflowId)}/execute`;
425
+ try {
426
+ const res = await this.fetchImpl(url, {
427
+ method: "POST",
428
+ headers: this.buildHeaders(),
429
+ body: JSON.stringify({ input, options })
430
+ });
431
+ const data = await this.safeJson(res);
432
+ if (!res.ok) {
433
+ return { success: false, error: data?.error || `HTTP ${res.status}` };
434
+ }
435
+ return data || { success: true };
436
+ } catch (error) {
437
+ return { success: false, error: error instanceof Error ? error.message : "Network error" };
438
+ }
439
+ }
440
+ };
441
+ function createAIWorkflowClient(options = {}) {
442
+ return new AIWorkflowClient(options);
443
+ }
444
+ var aiWorkflow = createAIWorkflowClient({ baseUrl: "https://evoagentx-server" });
445
+
446
+ // src/services/request/index.ts
447
+ import axios from "axios";
448
+ var Request = class {
449
+ constructor(config) {
450
+ this.abortControllers = /* @__PURE__ */ new Map();
451
+ this.instance = axios.create({
452
+ ...config,
453
+ validateStatus: (status) => {
454
+ return status >= 200 && status < 300;
455
+ }
456
+ });
457
+ this.interceptors = config.interceptors;
458
+ this.instance.interceptors.request.use(
459
+ this.interceptors?.requestInterceptor,
460
+ this.interceptors?.requestInterceptorCatch
461
+ );
462
+ this.instance.interceptors.response.use(
463
+ this.interceptors?.responseInterceptor,
464
+ this.interceptors?.responseInterceptorCatch
465
+ );
466
+ this.instance.interceptors.request.use(
467
+ (config2) => {
468
+ return config2;
469
+ },
470
+ (err) => {
471
+ return Promise.reject(err);
472
+ }
473
+ );
474
+ this.instance.interceptors.response.use(
475
+ (res) => {
476
+ return res.data;
477
+ },
478
+ (err) => {
479
+ if (axios.isCancel(err)) {
480
+ return Promise.reject({
481
+ isCanceled: true,
482
+ message: "request canceled",
483
+ originalError: err
484
+ });
485
+ }
486
+ if (err.response?.data?.error) {
487
+ return Promise.reject(err.response.data.error);
488
+ }
489
+ return Promise.reject(err);
490
+ }
491
+ );
492
+ }
493
+ cancelRequest(url) {
494
+ this.abortControllers.forEach((controller, key) => {
495
+ if (key.includes(url)) {
496
+ controller.abort();
497
+ this.abortControllers.delete(key);
498
+ }
499
+ });
500
+ }
501
+ cancelAllRequests() {
502
+ this.abortControllers.forEach((controller) => {
503
+ controller.abort();
504
+ });
505
+ this.abortControllers.clear();
506
+ }
507
+ request(config) {
508
+ const controller = new AbortController();
509
+ const url = config.url || "";
510
+ const method = config.method || "GET";
511
+ const key = `${method}:${url}`;
512
+ this.abortControllers.set(key, controller);
513
+ config.signal = controller.signal;
514
+ return new Promise((resolve, reject) => {
515
+ if (config.interceptors?.requestInterceptor) {
516
+ config = config.interceptors.requestInterceptor(config);
517
+ }
518
+ this.instance.request(config).then((res) => {
519
+ this.abortControllers.delete(key);
520
+ if (config.interceptors?.responseInterceptor) {
521
+ res = config.interceptors.responseInterceptor(res);
522
+ }
523
+ resolve(res);
524
+ }).catch((err) => {
525
+ this.abortControllers.delete(key);
526
+ reject(err);
527
+ });
528
+ });
529
+ }
530
+ get(config) {
531
+ return this.request({ ...config, method: "GET" });
532
+ }
533
+ post(config) {
534
+ return this.request({ ...config, method: "POST" });
535
+ }
536
+ delete(config) {
537
+ return this.request({ ...config, method: "DELETE" });
538
+ }
539
+ put(config) {
540
+ return this.request({ ...config, method: "PUT" });
541
+ }
542
+ patch(config) {
543
+ return this.request({ ...config, method: "PATCH" });
544
+ }
545
+ };
546
+ var request_default = Request;
547
+
548
+ // src/services/ai-workflow-axios.ts
549
+ function createAIWorkflowClientAxios(options = {}) {
550
+ const basePath = options.basePath ?? "/api";
551
+ const baseUrl = (options.baseUrl || "https://evoagentx-server.fly.dev").replace(/\/+$/, "");
552
+ const baseAPI = `${baseUrl}${basePath.startsWith("/") ? "" : "/"}${basePath}`.replace(/\/+$/, "");
553
+ const client = options.requestInstance || new request_default({
554
+ baseURL: baseAPI,
555
+ timeout: options.timeout ?? 6e4,
556
+ interceptors: {
557
+ requestInterceptor: (config) => {
558
+ config.headers = config.headers || {};
559
+ if (options.apiKey && !config.headers["Authorization"]) {
560
+ config.headers["Authorization"] = `Bearer ${options.apiKey}`;
561
+ }
562
+ if (options.headers) {
563
+ config.headers = { ...config.headers || {}, ...options.headers };
564
+ }
565
+ return config;
566
+ },
567
+ requestInterceptorCatch: (err) => Promise.reject(err),
568
+ responseInterceptor: (res) => res,
569
+ responseInterceptorCatch: (err) => Promise.reject(err)
570
+ }
571
+ });
572
+ return {
573
+ async executeWorkflow(workflowId, input, opts) {
574
+ const url = `${baseUrl}/workflow/${encodeURIComponent(workflowId)}/execute`;
575
+ const data = await client.post({ url, data: { input, options: opts } });
576
+ return data;
577
+ }
578
+ };
579
+ }
580
+
581
+ // src/services/artifact-types.ts
582
+ function canAccessArtifact(a, ctx = {}) {
583
+ if (!a) return false;
584
+ if (a.visibility === "public") return true;
585
+ if (a.visibility === "project") {
586
+ if (ctx.projectId && a.projectId && ctx.projectId === a.projectId) return true;
587
+ if (ctx.tokenScopes && ctx.tokenScopes.includes("project:read")) return true;
588
+ return false;
589
+ }
590
+ if (a.visibility === "private") {
591
+ if (ctx.userId && a.ownerId && ctx.userId === a.ownerId) return true;
592
+ if (ctx.tokenScopes && (ctx.tokenScopes.includes("artifact:read:all") || ctx.tokenScopes.includes("admin"))) return true;
593
+ return false;
594
+ }
595
+ if (a.visibility === "shared") {
596
+ if (ctx.userId && a.sharedWith && a.sharedWith.includes(ctx.userId)) return true;
597
+ if (ctx.tokenScopes && (ctx.tokenScopes.includes("artifact:read:all") || ctx.tokenScopes.includes("admin"))) return true;
598
+ return false;
599
+ }
600
+ return false;
601
+ }
602
+
603
+ // src/services/artifacts-client.ts
604
+ function createArtifactsClient(req) {
605
+ return {
606
+ async create(input) {
607
+ return await req.post({ url: "/artifacts", data: input });
608
+ },
609
+ async list(query) {
610
+ return await req.get({ url: "/artifacts", params: query });
611
+ },
612
+ async get(id) {
613
+ return await req.get({ url: `/artifacts/${encodeURIComponent(id)}` });
614
+ },
615
+ async setVisibility(id, visibility) {
616
+ await req.patch({ url: `/artifacts/${encodeURIComponent(id)}/visibility`, data: { visibility } });
617
+ },
618
+ async delete(id) {
619
+ await req.delete({ url: `/artifacts/${encodeURIComponent(id)}` });
620
+ },
621
+ // convenience local check (server is authoritative)
622
+ canAccessLocal(a, ctx) {
623
+ if (!a) return false;
624
+ if (a.visibility === "public") return true;
625
+ if (a.visibility === "project") return Boolean(ctx.projectId && a.projectId && ctx.projectId === a.projectId);
626
+ if (a.visibility === "private") return Boolean(ctx.userId && a.ownerId && ctx.userId === a.ownerId);
627
+ if (a.visibility === "shared") return Boolean(ctx.userId && a.sharedWith && a.sharedWith.includes(ctx.userId));
628
+ return false;
629
+ }
630
+ };
631
+ }
632
+
633
+ // src/services/index.ts
634
+ var request = new request_default({
635
+ baseURL: "https://create-x-backend.fly.dev/api",
636
+ timeout: 6e4,
637
+ interceptors: {
638
+ requestInterceptor: (config) => {
639
+ config.headers = config.headers || {};
640
+ return config;
641
+ },
642
+ requestInterceptorCatch: (err) => {
643
+ return Promise.reject(err);
644
+ },
645
+ responseInterceptor: (res) => {
646
+ return res;
647
+ },
648
+ responseInterceptorCatch: (err) => {
649
+ return Promise.reject(err);
650
+ }
651
+ }
652
+ });
653
+ var aiRequest = new request_default({
654
+ baseURL: "https://evoagentx-server.fly.dev",
655
+ timeout: 6e5,
656
+ interceptors: {
657
+ requestInterceptor: (config) => {
658
+ config.headers = config.headers || {};
659
+ return config;
660
+ },
661
+ requestInterceptorCatch: (err) => {
662
+ return Promise.reject(err);
663
+ },
664
+ responseInterceptor: (res) => {
665
+ return res;
666
+ },
667
+ responseInterceptorCatch: (err) => {
668
+ return Promise.reject(err);
669
+ }
670
+ }
671
+ });
672
+ var workflowRequest = aiRequest;
673
+ function createClient(opts) {
674
+ const biz = opts?.requestInstance || request;
675
+ const ai = opts?.aiRequestInstance || aiRequest;
676
+ let token = null;
677
+ function applyToken(t) {
678
+ try {
679
+ try {
680
+ if (biz && biz.instance) {
681
+ if (t) biz.instance.defaults.headers.common["Authorization"] = `Bearer ${t}`;
682
+ else delete biz.instance.defaults.headers.common["Authorization"];
683
+ }
684
+ if (ai && ai.instance) {
685
+ if (t) ai.instance.defaults.headers.common["Authorization"] = `Bearer ${t}`;
686
+ else delete ai.instance.defaults.headers.common["Authorization"];
687
+ }
688
+ } catch (_e) {
689
+ }
690
+ } catch (_e) {
691
+ }
692
+ }
693
+ const runtimeMode = (() => {
694
+ if (opts?.mode) return opts.mode;
695
+ try {
696
+ if (typeof window !== "undefined") return window.self !== window.top ? "embedded" : "standalone";
697
+ } catch (_e) {
698
+ return "standalone";
699
+ }
700
+ return "standalone";
701
+ })();
702
+ async function initToken() {
703
+ if (opts?.auth?.getToken) {
704
+ try {
705
+ const t = await opts.auth.getToken();
706
+ if (t) {
707
+ token = t;
708
+ applyToken(token);
709
+ return;
710
+ }
711
+ } catch (_e) {
712
+ }
713
+ }
714
+ if (runtimeMode === "embedded" && opts?.auth?.tokenInjection) {
715
+ const allowed = opts.auth.tokenInjection.allowedOrigins || [];
716
+ const waitMs = opts.auth.tokenInjection.waitMs ?? 3e3;
717
+ const tokenFromPostMessage = await new Promise((resolve) => {
718
+ let resolved = false;
719
+ function handler(ev) {
720
+ try {
721
+ if (!ev.data || typeof ev.data !== "object") return;
722
+ if (ev.data.type !== "howone:token") return;
723
+ if (allowed.length > 0 && !allowed.includes(ev.origin)) return;
724
+ const t = ev.data.token;
725
+ if (t && !resolved) {
726
+ resolved = true;
727
+ window.removeEventListener("message", handler);
728
+ resolve(String(t));
729
+ }
730
+ } catch (_e) {
731
+ }
732
+ }
733
+ window.addEventListener("message", handler);
734
+ setTimeout(() => {
735
+ if (!resolved) {
736
+ resolved = true;
737
+ window.removeEventListener("message", handler);
738
+ resolve(null);
739
+ }
740
+ }, waitMs);
741
+ });
742
+ if (tokenFromPostMessage) {
743
+ token = tokenFromPostMessage;
744
+ applyToken(token);
745
+ return;
746
+ }
747
+ }
748
+ }
749
+ try {
750
+ if (typeof window !== "undefined") {
751
+ void initToken();
752
+ }
753
+ } catch (_e) {
754
+ }
755
+ return {
756
+ request: biz,
757
+ aiRequest: ai,
758
+ workflowRequest: ai,
759
+ // artifact helpers using artifacts-client
760
+ artifacts: createArtifactsClient(biz),
761
+ // auth helpers
762
+ auth: {
763
+ setToken: (t) => {
764
+ token = t;
765
+ applyToken(t);
766
+ },
767
+ getToken: () => token,
768
+ isAuthenticated: () => Boolean(token),
769
+ // minimal login/logout stubs - consumers can override behavior
770
+ login: (redirect) => {
771
+ if (opts?.authRequired) {
772
+ if (typeof window !== "undefined") {
773
+ const loc = redirect || window.location.href;
774
+ window.location.href = `/login?redirect=${encodeURIComponent(loc)}`;
775
+ }
776
+ }
777
+ },
778
+ logout: () => {
779
+ token = null;
780
+ applyToken(null);
781
+ }
782
+ }
783
+ };
784
+ }
785
+
786
+ // src/components/auth/LoginForm.tsx
787
+ import { useState, useEffect } from "react";
788
+ import { Icon } from "@iconify/react";
789
+ import { Loader2 } from "lucide-react";
790
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
791
+ var LoginForm = ({
792
+ onLoginSuccess,
793
+ appName = "AI Application Platform",
794
+ className = ""
795
+ }) => {
796
+ const [email, setEmail] = useState("");
797
+ const [code, setCode] = useState("");
798
+ const [validationErrors, setValidationErrors] = useState({});
799
+ const [isAnyLoading, setIsAnyLoading] = useState(false);
800
+ const [codeSent, setCodeSent] = useState(false);
801
+ const [loginError, setLoginError] = useState(null);
802
+ const googleLogin = async () => {
803
+ console.log("Google login clicked");
804
+ };
805
+ const githubLogin = async () => {
806
+ console.log("GitHub login clicked");
807
+ };
808
+ const sendEmailCode = async (email2) => {
809
+ console.log("Send code to:", email2, "for app:", appName);
810
+ setCodeSent(true);
811
+ };
812
+ const loginWithEmail = async (email2, code2) => {
813
+ console.log("Login with email:", email2, "code:", code2);
814
+ if (onLoginSuccess) onLoginSuccess();
815
+ };
816
+ const clearError = () => {
817
+ setLoginError(null);
818
+ setValidationErrors({});
819
+ };
820
+ useEffect(() => {
821
+ if (loginError) {
822
+ try {
823
+ const errorObj = JSON.parse(loginError);
824
+ const newErrors = {};
825
+ if (errorObj.code === 429) {
826
+ newErrors.form = errorObj.msg || "\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5";
827
+ } else if (errorObj.data?.code === 401 && errorObj.data?.message) {
828
+ if (codeSent) {
829
+ newErrors.code = errorObj.data.message;
830
+ } else {
831
+ newErrors.form = errorObj.data.message;
832
+ }
833
+ } else if (errorObj.msg) {
834
+ newErrors.form = errorObj.msg;
835
+ } else if (errorObj.data?.message) {
836
+ newErrors.form = errorObj.data.message;
837
+ } else {
838
+ newErrors.form = "\u53D1\u751F\u672A\u77E5\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5";
839
+ }
840
+ setValidationErrors(newErrors);
841
+ } catch (e) {
842
+ setValidationErrors({ form: loginError });
843
+ }
844
+ const timer = setTimeout(() => {
845
+ clearError();
846
+ }, 8e3);
847
+ return () => clearTimeout(timer);
848
+ }
849
+ }, [loginError, codeSent]);
850
+ const handleSubmit = async (e) => {
851
+ e.preventDefault();
852
+ const formData = new FormData(e.currentTarget);
853
+ setValidationErrors({});
854
+ if (!codeSent) {
855
+ const emailValue = formData.get("email");
856
+ if (!emailValue) {
857
+ setValidationErrors({ email: "Please enter your email address" });
858
+ return;
859
+ }
860
+ setIsAnyLoading(true);
861
+ try {
862
+ await sendEmailCode(emailValue);
863
+ setEmail(emailValue);
864
+ } catch (error) {
865
+ setLoginError(error instanceof Error ? error.message : "Failed to send code");
866
+ } finally {
867
+ setIsAnyLoading(false);
868
+ }
869
+ } else {
870
+ const codeValue = code;
871
+ if (!codeValue || codeValue.length !== 6) {
872
+ setValidationErrors({ code: "Please enter the 6-digit verification code" });
873
+ return;
874
+ }
875
+ setIsAnyLoading(true);
876
+ try {
877
+ await loginWithEmail(email, codeValue);
878
+ } catch (error) {
879
+ setLoginError(error instanceof Error ? error.message : "Login failed");
880
+ } finally {
881
+ setIsAnyLoading(false);
882
+ }
883
+ }
884
+ };
885
+ return /* @__PURE__ */ jsxs2("div", { className: `w-full space-y-6 ${className}`, children: [
886
+ /* @__PURE__ */ jsxs2("div", { className: "space-y-1", children: [
887
+ /* @__PURE__ */ jsx2("h1", { className: "text-3xl font-bold text-gray-900", children: "Welcome Back!" }),
888
+ /* @__PURE__ */ jsx2("p", { className: "text-sm text-gray-600", children: "Please enter log in details below" })
889
+ ] }),
890
+ /* @__PURE__ */ jsxs2("form", { className: "space-y-5", onSubmit: handleSubmit, children: [
891
+ /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
892
+ /* @__PURE__ */ jsx2("label", { htmlFor: "email", className: "text-gray-700 font-medium text-sm block", children: "Email" }),
893
+ /* @__PURE__ */ jsx2(
894
+ "input",
895
+ {
896
+ id: "email",
897
+ type: "email",
898
+ name: "email",
899
+ value: email,
900
+ onChange: (e) => {
901
+ const value = e.target.value;
902
+ setEmail(value);
903
+ if (validationErrors.email) {
904
+ const newErrors = { ...validationErrors };
905
+ delete newErrors.email;
906
+ setValidationErrors(newErrors);
907
+ }
908
+ },
909
+ required: true,
910
+ "aria-invalid": !!validationErrors.email,
911
+ 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",
912
+ placeholder: ""
913
+ }
914
+ ),
915
+ validationErrors.email && /* @__PURE__ */ jsx2("p", { className: "text-red-600 text-sm", children: validationErrors.email })
916
+ ] }),
917
+ codeSent && /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
918
+ /* @__PURE__ */ jsx2("label", { className: "text-gray-700 font-medium text-sm block", children: "Verification Code" }),
919
+ /* @__PURE__ */ jsx2(
920
+ "input",
921
+ {
922
+ type: "text",
923
+ maxLength: 6,
924
+ value: code,
925
+ onChange: (e) => {
926
+ const value = e.target.value.replace(/\D/g, "");
927
+ setCode(value);
928
+ if (validationErrors.code) {
929
+ const newErrors = { ...validationErrors };
930
+ delete newErrors.code;
931
+ setValidationErrors(newErrors);
932
+ }
933
+ },
934
+ "aria-invalid": !!validationErrors.code,
935
+ 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",
936
+ placeholder: "000000"
937
+ }
938
+ ),
939
+ validationErrors.code && /* @__PURE__ */ jsx2("p", { className: "text-red-600 text-sm", children: validationErrors.code })
940
+ ] }),
941
+ validationErrors.form && /* @__PURE__ */ jsx2("div", { className: "text-red-600 text-sm p-3 bg-red-50 rounded-md border border-red-200", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center", children: [
942
+ /* @__PURE__ */ jsx2(Icon, { icon: "material-symbols:error", className: "text-red-600 mr-2" }),
943
+ /* @__PURE__ */ jsx2("span", { children: validationErrors.form })
944
+ ] }) }),
945
+ /* @__PURE__ */ jsxs2(
946
+ "button",
947
+ {
948
+ type: "submit",
949
+ className: "w-full h-11 bg-black hover:bg-gray-800 text-white font-medium rounded-md text-sm disabled:opacity-70 flex items-center justify-center",
950
+ disabled: isAnyLoading || !email || codeSent && code.length !== 6,
951
+ "aria-busy": isAnyLoading,
952
+ children: [
953
+ isAnyLoading && /* @__PURE__ */ jsx2(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
954
+ codeSent ? isAnyLoading ? "Signing in..." : "Sign in" : isAnyLoading ? "Sending..." : "Send Code"
955
+ ]
956
+ }
957
+ )
958
+ ] }),
959
+ /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
960
+ /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
961
+ /* @__PURE__ */ jsx2("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx2("div", { className: "w-full border-t border-gray-200" }) }),
962
+ /* @__PURE__ */ jsx2("div", { className: "relative flex justify-center text-xs", children: /* @__PURE__ */ jsx2("span", { className: "px-4 text-gray-500", children: "or continue" }) })
963
+ ] }),
964
+ /* @__PURE__ */ jsxs2(
965
+ "button",
966
+ {
967
+ className: "w-full h-11 bg-white hover:bg-gray-50 text-gray-900 hover:text-gray-900 border border-gray-200 hover:border-gray-300 font-medium rounded-md text-sm disabled:opacity-70 flex items-center justify-center",
968
+ onClick: () => {
969
+ if (!isAnyLoading) {
970
+ clearError();
971
+ googleLogin();
972
+ }
973
+ },
974
+ disabled: isAnyLoading,
975
+ children: [
976
+ isAnyLoading ? /* @__PURE__ */ jsx2(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx2(Icon, { icon: "flat-color-icons:google", className: "w-6 h-6 mr-2" }),
977
+ isAnyLoading ? "Connecting..." : "Log in with Google"
978
+ ]
979
+ }
980
+ ),
981
+ /* @__PURE__ */ jsxs2(
982
+ "button",
983
+ {
984
+ className: "w-full h-11 bg-black hover:bg-gray-800 text-white font-medium rounded-md text-sm disabled:opacity-70 flex items-center justify-center",
985
+ onClick: () => {
986
+ if (!isAnyLoading) {
987
+ clearError();
988
+ githubLogin();
989
+ }
990
+ },
991
+ disabled: isAnyLoading,
992
+ children: [
993
+ isAnyLoading ? /* @__PURE__ */ jsx2(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx2(Icon, { icon: "mdi:github", className: "w-6 h-6 mr-2" }),
994
+ isAnyLoading ? "Connecting..." : "Log in with GitHub"
995
+ ]
996
+ }
997
+ )
998
+ ] })
999
+ ] });
1000
+ };
1001
+
1002
+ // src/components/auth/AuthGuard.tsx
1003
+ import { Navigate, useLocation } from "react-router-dom";
1004
+ import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1005
+ var AuthGuard = ({
1006
+ children,
1007
+ fallback,
1008
+ redirectTo = "/login",
1009
+ requireAuth = true,
1010
+ roles = [],
1011
+ permissions = []
1012
+ }) => {
1013
+ const isAuthenticated = false;
1014
+ const user = null;
1015
+ const isLoading = false;
1016
+ const location = useLocation();
1017
+ if (isLoading) {
1018
+ if (fallback) {
1019
+ return /* @__PURE__ */ jsx3(Fragment, { children: fallback });
1020
+ }
1021
+ return /* @__PURE__ */ jsx3("div", { className: "min-h-screen flex items-center justify-center", children: /* @__PURE__ */ jsx3("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600" }) });
1022
+ }
1023
+ if (requireAuth && !isAuthenticated) {
1024
+ return /* @__PURE__ */ jsx3(Navigate, { to: redirectTo, state: { from: location }, replace: true });
1025
+ }
1026
+ if (roles.length > 0 && user !== null) {
1027
+ const currentUser = user;
1028
+ if (currentUser.roles) {
1029
+ const hasRole = roles.some((role) => currentUser.roles.includes(role));
1030
+ if (!hasRole) {
1031
+ if (fallback) {
1032
+ return /* @__PURE__ */ jsx3(Fragment, { children: fallback });
1033
+ }
1034
+ return /* @__PURE__ */ jsx3("div", { className: "min-h-screen flex items-center justify-center", children: /* @__PURE__ */ jsxs3("div", { className: "text-center", children: [
1035
+ /* @__PURE__ */ jsx3("h1", { className: "text-2xl font-bold text-gray-900 mb-2", children: "Access Denied" }),
1036
+ /* @__PURE__ */ jsx3("p", { className: "text-gray-600", children: "You don't have the required role to access this page." })
1037
+ ] }) });
1038
+ }
1039
+ }
1040
+ }
1041
+ if (permissions.length > 0 && user !== null) {
1042
+ const currentUser = user;
1043
+ if (currentUser.permissions) {
1044
+ const hasPermission = permissions.some((permission) => currentUser.permissions.includes(permission));
1045
+ if (!hasPermission) {
1046
+ if (fallback) {
1047
+ return /* @__PURE__ */ jsx3(Fragment, { children: fallback });
1048
+ }
1049
+ return /* @__PURE__ */ jsx3("div", { className: "min-h-screen flex items-center justify-center", children: /* @__PURE__ */ jsxs3("div", { className: "text-center", children: [
1050
+ /* @__PURE__ */ jsx3("h1", { className: "text-2xl font-bold text-gray-900 mb-2", children: "Access Denied" }),
1051
+ /* @__PURE__ */ jsx3("p", { className: "text-gray-600", children: "You don't have the required permission to access this page." })
1052
+ ] }) });
1053
+ }
1054
+ }
1055
+ }
1056
+ return /* @__PURE__ */ jsx3(Fragment, { children });
1057
+ };
1058
+
1059
+ // src/components/ui/Loading.tsx
1060
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1061
+ var Loading = ({
1062
+ size = "md",
1063
+ text = "Loading...",
1064
+ className = "",
1065
+ fullScreen = false
1066
+ }) => {
1067
+ const sizeClasses = {
1068
+ sm: "h-4 w-4",
1069
+ md: "h-8 w-8",
1070
+ lg: "h-12 w-12"
1071
+ };
1072
+ 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";
1073
+ return /* @__PURE__ */ jsx4("div", { className: `${containerClasses} ${className}`, children: /* @__PURE__ */ jsxs4("div", { className: "text-center", children: [
1074
+ /* @__PURE__ */ jsx4(
1075
+ "div",
1076
+ {
1077
+ className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 mx-auto ${sizeClasses[size]}`
1078
+ }
1079
+ ),
1080
+ text && /* @__PURE__ */ jsx4("p", { className: "mt-2 text-sm text-gray-600", children: text })
1081
+ ] }) });
1082
+ };
1083
+ var LoadingSpinner = ({
1084
+ size = "md",
1085
+ className = ""
1086
+ }) => {
1087
+ const sizeClasses = {
1088
+ sm: "h-4 w-4",
1089
+ md: "h-8 w-8",
1090
+ lg: "h-12 w-12"
1091
+ };
1092
+ return /* @__PURE__ */ jsx4(
1093
+ "div",
1094
+ {
1095
+ className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 ${sizeClasses[size]} ${className}`
1096
+ }
1097
+ );
1098
+ };
1099
+
1100
+ // src/components/ui/ErrorBoundary.tsx
1101
+ import { Component } from "react";
1102
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1103
+ var ErrorBoundary = class extends Component {
1104
+ constructor(props) {
1105
+ super(props);
1106
+ this.handleRetry = () => {
1107
+ this.setState({ hasError: false, error: void 0, errorInfo: void 0 });
1108
+ };
1109
+ this.state = { hasError: false };
1110
+ }
1111
+ static getDerivedStateFromError(error) {
1112
+ return { hasError: true, error };
1113
+ }
1114
+ componentDidCatch(error, errorInfo) {
1115
+ this.setState({
1116
+ error,
1117
+ errorInfo
1118
+ });
1119
+ this.props.onError?.(error, errorInfo);
1120
+ }
1121
+ render() {
1122
+ if (this.state.hasError) {
1123
+ if (this.props.fallback) {
1124
+ const FallbackComponent = this.props.fallback;
1125
+ return /* @__PURE__ */ jsx5(FallbackComponent, { error: this.state.error, retry: this.handleRetry });
1126
+ }
1127
+ return /* @__PURE__ */ jsx5("div", { className: "min-h-[400px] flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs5("div", { className: "text-center max-w-md", children: [
1128
+ /* @__PURE__ */ jsx5("div", { className: "text-red-500 text-6xl mb-4", children: "\u26A0\uFE0F" }),
1129
+ /* @__PURE__ */ jsx5("h2", { className: "text-xl font-semibold text-gray-900 mb-2", children: "Something went wrong" }),
1130
+ /* @__PURE__ */ jsx5("p", { className: "text-gray-600 mb-4", children: "An unexpected error occurred. Please try refreshing the page." }),
1131
+ /* @__PURE__ */ jsx5(
1132
+ "button",
1133
+ {
1134
+ onClick: this.handleRetry,
1135
+ className: "px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors",
1136
+ children: "Try Again"
1137
+ }
1138
+ ),
1139
+ false
1140
+ ] }) });
1141
+ }
1142
+ return this.props.children;
1143
+ }
1144
+ };
1145
+ var DefaultErrorFallback = ({ retry }) => /* @__PURE__ */ jsx5("div", { className: "min-h-[200px] flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs5("div", { className: "text-center", children: [
1146
+ /* @__PURE__ */ jsx5("div", { className: "text-red-500 text-4xl mb-2", children: "\u26A0\uFE0F" }),
1147
+ /* @__PURE__ */ jsx5("p", { className: "text-gray-600 mb-2", children: "Something went wrong" }),
1148
+ retry && /* @__PURE__ */ jsx5(
1149
+ "button",
1150
+ {
1151
+ onClick: retry,
1152
+ className: "px-3 py-1 bg-blue-600 text-white text-sm rounded hover:bg-blue-700 transition-colors",
1153
+ children: "Retry"
1154
+ }
1155
+ )
1156
+ ] }) });
1157
+
1158
+ // src/hooks/use-mobile.ts
1159
+ import * as React3 from "react";
1160
+ var MOBILE_BREAKPOINT = 768;
1161
+ function useIsMobile() {
1162
+ const [isMobile, setIsMobile] = React3.useState(void 0);
1163
+ React3.useEffect(() => {
1164
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
1165
+ const onChange = () => {
1166
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
1167
+ };
1168
+ mql.addEventListener("change", onChange);
1169
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
1170
+ return () => mql.removeEventListener("change", onChange);
1171
+ }, []);
1172
+ return !!isMobile;
1173
+ }
1174
+
1175
+ // src/hooks/use-local-storage.ts
1176
+ import { useState as useState3 } from "react";
1177
+ function useLocalStorage(key, initialValue) {
1178
+ const [storedValue, setStoredValue] = useState3(() => {
1179
+ try {
1180
+ const item = window.localStorage.getItem(key);
1181
+ return item ? JSON.parse(item) : initialValue;
1182
+ } catch (error) {
1183
+ console.error(`Error reading localStorage key "${key}":`, error);
1184
+ return initialValue;
1185
+ }
1186
+ });
1187
+ const setValue = (value) => {
1188
+ try {
1189
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
1190
+ setStoredValue(valueToStore);
1191
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
1192
+ } catch (error) {
1193
+ console.error(`Error setting localStorage key "${key}":`, error);
1194
+ }
1195
+ };
1196
+ const removeValue = () => {
1197
+ try {
1198
+ window.localStorage.removeItem(key);
1199
+ setStoredValue(initialValue);
1200
+ } catch (error) {
1201
+ console.error(`Error removing localStorage key "${key}":`, error);
1202
+ }
1203
+ };
1204
+ return [storedValue, setValue, removeValue];
1205
+ }
1206
+
1207
+ // src/hooks/use-debounce.ts
1208
+ import { useState as useState4, useEffect as useEffect3 } from "react";
1209
+ function useDebounce(value, delay) {
1210
+ const [debouncedValue, setDebouncedValue] = useState4(value);
1211
+ useEffect3(() => {
1212
+ const handler = setTimeout(() => {
1213
+ setDebouncedValue(value);
1214
+ }, delay);
1215
+ return () => {
1216
+ clearTimeout(handler);
1217
+ };
1218
+ }, [value, delay]);
1219
+ return debouncedValue;
1220
+ }
1221
+
1222
+ // src/utils/earlyErrorHandler.ts
1223
+ function injectEarlyErrorHandler() {
1224
+ if (typeof window === "undefined" || typeof document === "undefined") return;
1225
+ const code = `
1226
+ (function () {
1227
+ const isIframe = window.self !== window.top;
1228
+ console.log("isIframe", isIframe);
1229
+
1230
+ console.log("[\u65E9\u671F\u9519\u8BEF\u5904\u7406] \u521D\u59CB\u5316");
1231
+
1232
+ window.__SEND_ERROR_TO_PARENT__ = function (error, details) {
1233
+ try {
1234
+ const errorPayload = {
1235
+ message: error instanceof Error ? error.message : String(error),
1236
+ stack: error instanceof Error ? error.stack : undefined,
1237
+ filename: details?.file || details?.filename,
1238
+ lineno: details?.line,
1239
+ colno: details?.column,
1240
+ timestamp: Date.now(),
1241
+ type: details?.type || "compile-error",
1242
+ details: details,
1243
+ };
1244
+
1245
+ window.parent.postMessage({ type: "ERROR_EVENT", payload: errorPayload }, "*");
1246
+ console.log("[\u65E9\u671F\u9519\u8BEF\u5904\u7406] \u9519\u8BEF\u5DF2\u53D1\u9001\u5230\u7236\u7A97\u53E3:", errorPayload);
1247
+ } catch (e) {
1248
+ console.error("[\u65E9\u671F\u9519\u8BEF\u5904\u7406] \u53D1\u9001\u9519\u8BEF\u5230\u7236\u7A97\u53E3\u5931\u8D25:", e);
1249
+ }
1250
+ };
1251
+
1252
+ function setupViteOverlayObserver() {
1253
+ if (!window.MutationObserver) return;
1254
+
1255
+ console.log("[\u65E9\u671F\u9519\u8BEF\u5904\u7406] \u8BBE\u7F6E Vite \u9519\u8BEF overlay \u76D1\u542C\u5668");
1256
+
1257
+ function processViteErrorOverlay(overlay) {
1258
+ try {
1259
+ if (overlay.hasAttribute("data-error-sent")) return;
1260
+ const shadowRoot = overlay.shadowRoot;
1261
+ if (!shadowRoot) return;
1262
+
1263
+ const messageElement = shadowRoot.querySelector("pre.message");
1264
+ const fileElement = shadowRoot.querySelector("pre.file");
1265
+ const frameElements = shadowRoot.querySelectorAll("pre.frame");
1266
+ const stackElement = shadowRoot.querySelector("pre.stack");
1267
+
1268
+ const message = messageElement ? messageElement.textContent : "";
1269
+ const file = fileElement ? fileElement.textContent : "";
1270
+ const frames = Array.from(frameElements).map((el) => el.textContent).join("
1271
+ ");
1272
+ const stack = stackElement ? stackElement.textContent : "";
1273
+
1274
+ let line, column;
1275
+ const fileStr = file || "";
1276
+ const lineColMatch = fileStr.match(/(?:line|at|:)(?:.*?)(?::| )(d+)(?::| )(d+)/i);
1277
+ if (lineColMatch) {
1278
+ line = parseInt(lineColMatch[1], 10);
1279
+ column = parseInt(lineColMatch[2], 10);
1280
+ }
1281
+
1282
+ const messageStr = message || "";
1283
+ const isReactError =
1284
+ messageStr.includes("React") ||
1285
+ messageStr.includes("JSX") ||
1286
+ messageStr.includes("Unexpected token") ||
1287
+ messageStr.includes("vite:react-babel");
1288
+
1289
+ const viteError = new Error(messageStr);
1290
+
1291
+ window.__SEND_ERROR_TO_PARENT__(viteError, {
1292
+ file,
1293
+ line,
1294
+ column,
1295
+ frames,
1296
+ stack,
1297
+ isReactError,
1298
+ type: isReactError ? "react-syntax" : "vite-error-overlay",
1299
+ });
1300
+
1301
+ overlay.setAttribute("data-error-sent", "true");
1302
+ } catch (e) {
1303
+ console.error("[\u65E9\u671F\u9519\u8BEF\u5904\u7406] \u5904\u7406 vite-error-overlay \u5931\u8D25:", e);
1304
+ }
1305
+ }
1306
+
1307
+ function checkExistingOverlays() {
1308
+ const viteErrorOverlays = document.querySelectorAll("vite-error-overlay");
1309
+ if (viteErrorOverlays.length > 0) {
1310
+ viteErrorOverlays.forEach((overlay) => {
1311
+ if (!overlay.hasAttribute("data-error-sent")) {
1312
+ processViteErrorOverlay(overlay);
1313
+ }
1314
+ });
1315
+ }
1316
+ }
1317
+
1318
+ const observer = new MutationObserver((mutations) => {
1319
+ for (const mutation of mutations) {
1320
+ if (mutation.addedNodes.length > 0) {
1321
+ for (const node of Array.from(mutation.addedNodes)) {
1322
+ if (node.nodeType === Node.ELEMENT_NODE) {
1323
+ const element = node;
1324
+ if (element.tagName === "VITE-ERROR-OVERLAY" && !element.hasAttribute("data-error-sent")) {
1325
+ setTimeout(() => processViteErrorOverlay(element), 100);
1326
+ }
1327
+ const viteErrorOverlays = element.querySelectorAll("vite-error-overlay");
1328
+ for (const viteErrorOverlay of Array.from(viteErrorOverlays)) {
1329
+ if (!viteErrorOverlay.hasAttribute("data-error-sent")) {
1330
+ setTimeout(() => processViteErrorOverlay(viteErrorOverlay), 100);
1331
+ }
1332
+ }
1333
+ }
1334
+ }
1335
+ }
1336
+ }
1337
+ });
1338
+
1339
+ observer.observe(document.documentElement, { childList: true, subtree: true, attributes: true, characterData: true });
1340
+ setTimeout(checkExistingOverlays, 500);
1341
+ setInterval(checkExistingOverlays, 2000);
1342
+ }
1343
+
1344
+ window.addEventListener(
1345
+ "error",
1346
+ function (event) {
1347
+ const target = event && (event.target || event.srcElement);
1348
+ const tagName = target && target.tagName;
1349
+ if (tagName) {
1350
+ const url = (target && (target.src || target.href || target.currentSrc)) || (target && target.getAttribute && (target.getAttribute('src') || target.getAttribute('href')));
1351
+ const preview = target && target.outerHTML ? String(target.outerHTML).slice(0, 300) : undefined;
1352
+ const resourceError = new Error('Resource load error: ' + tagName + ' ' + (url || 'unknown'));
1353
+ window.__SEND_ERROR_TO_PARENT__(resourceError, { filename: url, tagName: tagName, element: preview, type: "resource" });
1354
+ return;
1355
+ }
1356
+
1357
+ var stack = (event && event.error && event.error.stack) || "";
1358
+ var message = typeof event.message === "string" ? event.message : "";
1359
+ if ((stack && stack.indexOf('error-handler') !== -1) || !message) return;
1360
+
1361
+ window.__SEND_ERROR_TO_PARENT__(event.error || new Error(event.message), { filename: event.filename, line: event.lineno, column: event.colno, type: "runtime" });
1362
+ },
1363
+ true
1364
+ );
1365
+
1366
+ window.addEventListener("unhandledrejection", function (event) {
1367
+ const reason = event.reason;
1368
+ window.__SEND_ERROR_TO_PARENT__(reason instanceof Error ? reason : new Error(String(reason)), { type: "promise" });
1369
+ });
1370
+
1371
+ setupViteOverlayObserver();
1372
+
1373
+ if (!window.__CONSOLE_ERROR_INTERCEPTED__) {
1374
+ window.__CONSOLE_ERROR_INTERCEPTED__ = true;
1375
+ const originalConsoleError = console.error;
1376
+ console.error = function () {
1377
+ try {
1378
+ var args = Array.prototype.slice.call(arguments);
1379
+ var first = args[0];
1380
+ var firstStr = typeof first === "string" ? first : "";
1381
+ var isReact = firstStr.indexOf("React") !== -1;
1382
+ var isVite = firstStr.indexOf("[vite]") !== -1 || firstStr.indexOf("Failed to reload") !== -1;
1383
+ if (isReact || isVite) {
1384
+ var joined = args.map(function (a) {
1385
+ if (a instanceof Error) return a.message;
1386
+ if (typeof a === "string") return a;
1387
+ if (a && typeof a.message === "string") return a.message;
1388
+ try { return JSON.stringify(a); } catch (e) { return String(a); }
1389
+ }).join(" ");
1390
+ var errorForReport = new Error(joined);
1391
+ window.__SEND_ERROR_TO_PARENT__(errorForReport, { type: "runtime", viteErrorType: "console" });
1392
+ }
1393
+ } catch (e) { void e }
1394
+ return originalConsoleError.apply(console, arguments);
1395
+ };
1396
+ }
1397
+
1398
+ console.log("[\u65E9\u671F\u9519\u8BEF\u5904\u7406] \u521D\u59CB\u5316\u5B8C\u6210");
1399
+ })();
1400
+ `;
1401
+ try {
1402
+ const script = document.createElement("script");
1403
+ script.type = "text/javascript";
1404
+ script.text = code;
1405
+ const parent = document.head || document.documentElement;
1406
+ parent.prepend(script);
1407
+ } catch (e) {
1408
+ void e;
1409
+ }
1410
+ }
1411
+ export {
1412
+ AuthGuard,
1413
+ DefaultErrorFallback,
1414
+ ErrorBoundary,
1415
+ FloatingButton,
1416
+ Loading,
1417
+ LoadingSpinner,
1418
+ LoginForm,
1419
+ aiRequest,
1420
+ aiWorkflow,
1421
+ canAccessArtifact,
1422
+ createAIWorkflowClient,
1423
+ createAIWorkflowClientAxios,
1424
+ createArtifactsClient,
1425
+ createClient,
1426
+ getCodeStatus,
1427
+ injectEarlyErrorHandler,
1428
+ loginWithEmailCode,
1429
+ request,
1430
+ sendEmailVerificationCode,
1431
+ unifiedAuth,
1432
+ unifiedOAuth,
1433
+ useDebounce,
1434
+ useIsMobile,
1435
+ useLocalStorage,
1436
+ workflowRequest
1437
+ };
1438
+ //# sourceMappingURL=index.mjs.map