@howone/sdk 0.3.2 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -256,21 +256,16 @@ __export(index_exports, {
256
256
  AUTH_TOKEN_KEY: () => AUTH_TOKEN_KEY,
257
257
  ClayxButton: () => ClayxButton,
258
258
  ClayxToast: () => ClayxToast,
259
- DEFAULT_SELECTOR_CONFIG: () => DEFAULT_SELECTOR_CONFIG,
260
259
  DefaultErrorFallback: () => DefaultErrorFallback,
261
- ERROR_CONFIG: () => ERROR_CONFIG,
262
260
  ElementSelector: () => ElementSelector,
263
261
  ElementSelectorProvider: () => ElementSelectorProvider,
264
262
  ErrorBoundary: () => ErrorBoundary,
265
- ErrorHandler: () => ErrorHandler,
266
263
  FloatingButton: () => FloatingButton,
267
- GLOBAL_CONFIG: () => GLOBAL_CONFIG,
268
264
  GlobalToastContainer: () => GlobalToastContainer,
269
265
  HowOneProvider: () => HowOneProvider,
270
266
  Loading: () => Loading,
271
267
  LoadingSpinner: () => LoadingSpinner,
272
268
  LoginForm: () => LoginForm,
273
- SimpleErrorHandler: () => SimpleErrorHandler,
274
269
  ThemeProvider: () => ThemeProvider,
275
270
  ThemeToggle: () => ThemeToggle,
276
271
  aiWorkflow: () => aiWorkflow,
@@ -1442,6 +1437,7 @@ var HowOneProvider = ({
1442
1437
  isAuthenticated: hasCheckedUrlToken && !!token,
1443
1438
  logout
1444
1439
  };
1440
+ if (!hasCheckedUrlToken) return null;
1445
1441
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1446
1442
  ThemeProvider,
1447
1443
  {
@@ -3701,3628 +3697,6 @@ function useWorkflowStream() {
3701
3697
  };
3702
3698
  }
3703
3699
 
3704
- // src/utils/unified-error-handler/types.ts
3705
- var ERROR_CONFIG = {
3706
- MAX_ERRORS: 100,
3707
- MAX_INTERACTIONS: 50,
3708
- DEDUP_WINDOW: 1e3,
3709
- DEBOUNCE_TIME: 100,
3710
- CACHE_DURATION: 3e5,
3711
- SEVERITY_KEYWORDS: {
3712
- CRITICAL: ["fatal", "critical", "security", "crash", "corruption"],
3713
- HIGH: ["error", "exception", "failed", "timeout", "network error"],
3714
- MEDIUM: ["warning", "deprecated", "slow", "performance"],
3715
- LOW: ["info", "debug", "trace", "notice"]
3716
- },
3717
- CATEGORY_KEYWORDS: {
3718
- SYNTAX: ["syntaxerror", "unexpected token", "parse error", "invalid syntax", "expected", "transform failed"],
3719
- NETWORK: ["fetch", "xhr", "network", "cors", "timeout", "connection"],
3720
- RUNTIME: ["referenceerror", "typeerror", "rangeerror", "undefined"],
3721
- SECURITY: ["csp", "xss", "csrf", "security", "unauthorized"],
3722
- PERFORMANCE: ["slow", "memory", "leak", "performance", "timeout"],
3723
- DEVELOPMENT: ["vite", "hmr", "hot reload", "dev server", "webpack", "esbuild", "plugin:vite:esbuild"]
3724
- }
3725
- };
3726
- var GLOBAL_CONFIG = {
3727
- ALLOWED_ORIGINS: [
3728
- "https://howone.ai",
3729
- "https://howone.dev",
3730
- "http://localhost:3000",
3731
- "http://localhost:5173"
3732
- ],
3733
- DEBOUNCE_DELAY: 10,
3734
- OVERRIDE_STYLESHEET_ID: "howone-override-styles"
3735
- };
3736
- var DEFAULT_SELECTOR_CONFIG = {
3737
- HIGHLIGHT_COLOR: "#ff6b6b",
3738
- HIGHLIGHT_BORDER_WIDTH: "2px",
3739
- HIGHLIGHT_BORDER_STYLE: "solid",
3740
- SELECTED_COLOR: "#4ecdc4",
3741
- SELECTED_BORDER_WIDTH: "3px",
3742
- TOOLTIP_BACKGROUND: "#333",
3743
- TOOLTIP_COLOR: "#fff",
3744
- TOOLTIP_PADDING: "8px 12px",
3745
- TOOLTIP_BORDER_RADIUS: "4px",
3746
- TOOLTIP_FONT_SIZE: "12px",
3747
- TOOLTIP_Z_INDEX: "10000",
3748
- FULL_WIDTH_TOOLTIP_OFFSET: 10,
3749
- highlightClass: "howone-highlight",
3750
- selectedClass: "howone-selected",
3751
- cursor: "crosshair"
3752
- };
3753
-
3754
- // src/utils/unified-error-handler/utils/DeepSerializer.ts
3755
- var CircularReference = class {
3756
- constructor(path) {
3757
- this.message = `[Circular Reference to ${path}]`;
3758
- }
3759
- };
3760
- var TypeWrapper = class {
3761
- constructor(type, value) {
3762
- this._type = type;
3763
- this.value = value;
3764
- }
3765
- };
3766
- var DeepSerializer = class {
3767
- /**
3768
- * 深度序列化对象
3769
- */
3770
- static serialize(obj, options = {}, visitedObjects = /* @__PURE__ */ new WeakMap(), path = "root") {
3771
- const opts = { ...this.DEFAULT_OPTIONS, ...options };
3772
- if (path.split(".").length > opts.maxDepth) {
3773
- return new TypeWrapper(
3774
- "MaxDepthReached",
3775
- `[Max depth of ${opts.maxDepth} reached]`
3776
- );
3777
- }
3778
- if (obj === void 0) {
3779
- return new TypeWrapper("undefined", "undefined");
3780
- }
3781
- if (obj === null) {
3782
- return null;
3783
- }
3784
- if (typeof obj === "string") {
3785
- return obj.length > opts.maxStringLength ? new TypeWrapper(
3786
- "String",
3787
- `${obj.slice(0, opts.maxStringLength)}... [${obj.length - opts.maxStringLength} more characters]`
3788
- ) : obj;
3789
- }
3790
- if (typeof obj === "number") {
3791
- return Number.isNaN(obj) ? new TypeWrapper("Number", "NaN") : Number.isFinite(obj) ? obj : new TypeWrapper("Number", obj > 0 ? "Infinity" : "-Infinity");
3792
- }
3793
- if (typeof obj === "boolean") {
3794
- return obj;
3795
- }
3796
- if (typeof obj === "bigint") {
3797
- return new TypeWrapper("BigInt", obj.toString());
3798
- }
3799
- if (typeof obj === "symbol") {
3800
- return new TypeWrapper("Symbol", obj.toString());
3801
- }
3802
- if (typeof obj === "function") {
3803
- return new TypeWrapper("Function", {
3804
- name: obj.name || "anonymous",
3805
- stringValue: obj.toString().slice(0, opts.maxStringLength),
3806
- length: obj.length
3807
- });
3808
- }
3809
- if (obj && typeof obj === "object") {
3810
- if (visitedObjects.has(obj)) {
3811
- return new CircularReference(visitedObjects.get(obj));
3812
- }
3813
- visitedObjects.set(obj, path);
3814
- }
3815
- if (obj instanceof Error) {
3816
- return this.serializeError(obj, opts, visitedObjects, path);
3817
- }
3818
- if (obj instanceof Date) {
3819
- return new TypeWrapper("Date", {
3820
- iso: obj.toISOString(),
3821
- value: obj.valueOf(),
3822
- local: obj.toString()
3823
- });
3824
- }
3825
- if (obj instanceof RegExp) {
3826
- return new TypeWrapper("RegExp", {
3827
- source: obj.source,
3828
- flags: obj.flags,
3829
- string: obj.toString()
3830
- });
3831
- }
3832
- if (obj instanceof Promise) {
3833
- return new TypeWrapper("Promise", "[Promise]");
3834
- }
3835
- if (obj instanceof WeakMap || obj instanceof WeakSet) {
3836
- return new TypeWrapper(
3837
- obj.constructor.name,
3838
- "[" + obj.constructor.name + "]"
3839
- );
3840
- }
3841
- if (obj instanceof Set) {
3842
- return this.serializeSet(obj, opts, visitedObjects, path);
3843
- }
3844
- if (obj instanceof Map) {
3845
- return this.serializeMap(obj, opts, visitedObjects, path);
3846
- }
3847
- if (ArrayBuffer.isView(obj)) {
3848
- return this.serializeTypedArray(obj);
3849
- }
3850
- if (Array.isArray(obj)) {
3851
- return this.serializeArray(obj, opts, visitedObjects, path);
3852
- }
3853
- return this.serializeObject(obj, opts, visitedObjects, path);
3854
- }
3855
- /**
3856
- * 序列化错误对象
3857
- */
3858
- static serializeError(error, opts, visitedObjects, path) {
3859
- const errorObj = {
3860
- name: error.name,
3861
- message: error.message,
3862
- stack: error.stack
3863
- };
3864
- for (const key of Object.getOwnPropertyNames(error)) {
3865
- if (!errorObj[key]) {
3866
- try {
3867
- errorObj[key] = this.serialize(
3868
- error[key],
3869
- opts,
3870
- visitedObjects,
3871
- `${path}.${key}`
3872
- );
3873
- } catch (e) {
3874
- errorObj[key] = new TypeWrapper("Error", `[Unable to serialize: ${e}]`);
3875
- }
3876
- }
3877
- }
3878
- return new TypeWrapper("Error", errorObj);
3879
- }
3880
- /**
3881
- * 序列化 Set
3882
- */
3883
- static serializeSet(set, opts, visitedObjects, path) {
3884
- const values = Array.from(set);
3885
- if (values.length > opts.maxArrayLength) {
3886
- return new TypeWrapper("Set", {
3887
- values: values.slice(0, opts.maxArrayLength).map(
3888
- (item, index) => this.serialize(item, opts, visitedObjects, `${path}.Set[${index}]`)
3889
- ),
3890
- truncated: values.length - opts.maxArrayLength
3891
- });
3892
- }
3893
- return new TypeWrapper("Set", {
3894
- values: values.map(
3895
- (item, index) => this.serialize(item, opts, visitedObjects, `${path}.Set[${index}]`)
3896
- )
3897
- });
3898
- }
3899
- /**
3900
- * 序列化 Map
3901
- */
3902
- static serializeMap(map, opts, visitedObjects, path) {
3903
- const entries = {};
3904
- let truncatedCount = 0;
3905
- let addedCount = 0;
3906
- for (const [key, value] of map.entries()) {
3907
- if (addedCount >= opts.maxObjectKeys) {
3908
- truncatedCount++;
3909
- continue;
3910
- }
3911
- const keyString = typeof key === "object" ? JSON.stringify(
3912
- this.serialize(key, opts, visitedObjects, `${path}.MapKey`)
3913
- ) : String(key);
3914
- entries[keyString] = this.serialize(
3915
- value,
3916
- opts,
3917
- visitedObjects,
3918
- `${path}.Map[${keyString}]`
3919
- );
3920
- addedCount++;
3921
- }
3922
- return new TypeWrapper("Map", {
3923
- entries,
3924
- truncated: truncatedCount || void 0
3925
- });
3926
- }
3927
- /**
3928
- * 序列化 TypedArray
3929
- */
3930
- static serializeTypedArray(typedArray) {
3931
- const array = typedArray;
3932
- return new TypeWrapper(array.constructor.name, {
3933
- length: array.length,
3934
- byteLength: array.byteLength,
3935
- sample: Array.from(array.slice(0, 10))
3936
- });
3937
- }
3938
- /**
3939
- * 序列化数组
3940
- */
3941
- static serializeArray(array, opts, visitedObjects, path) {
3942
- if (array.length > opts.maxArrayLength) {
3943
- return array.slice(0, opts.maxArrayLength).map(
3944
- (item, index) => this.serialize(item, opts, visitedObjects, `${path}[${index}]`)
3945
- ).concat([`... ${array.length - opts.maxArrayLength} more items`]);
3946
- }
3947
- return array.map(
3948
- (item, index) => this.serialize(item, opts, visitedObjects, `${path}[${index}]`)
3949
- );
3950
- }
3951
- /**
3952
- * 序列化普通对象
3953
- */
3954
- static serializeObject(obj, opts, visitedObjects, path) {
3955
- const result = {};
3956
- let keys = [...Object.getOwnPropertyNames(obj)];
3957
- if (opts.includeSymbols) {
3958
- keys.push(
3959
- ...Object.getOwnPropertySymbols(obj).map((sym) => sym.toString())
3960
- );
3961
- }
3962
- let truncatedCount = 0;
3963
- keys.slice(0, opts.maxObjectKeys).forEach((key) => {
3964
- try {
3965
- const value = obj[key];
3966
- result[key] = this.serialize(
3967
- value,
3968
- opts,
3969
- visitedObjects,
3970
- `${path}.${key}`
3971
- );
3972
- } catch (error) {
3973
- result[key] = new TypeWrapper(
3974
- "Error",
3975
- `[Unable to serialize: ${error}]`
3976
- );
3977
- }
3978
- });
3979
- if (keys.length > opts.maxObjectKeys) {
3980
- truncatedCount = keys.length - opts.maxObjectKeys;
3981
- result["..."] = `${truncatedCount} more properties`;
3982
- }
3983
- return result;
3984
- }
3985
- /**
3986
- * 快速序列化(用于控制台输出)
3987
- */
3988
- static quickSerialize(obj) {
3989
- return this.serialize(obj, {
3990
- maxDepth: 5,
3991
- maxStringLength: 500,
3992
- maxArrayLength: 20,
3993
- maxObjectKeys: 20
3994
- });
3995
- }
3996
- };
3997
- DeepSerializer.DEFAULT_OPTIONS = {
3998
- maxDepth: 10,
3999
- indent: 2,
4000
- includeSymbols: true,
4001
- preserveTypes: true,
4002
- maxStringLength: 1e4,
4003
- maxArrayLength: 100,
4004
- maxObjectKeys: 100
4005
- };
4006
-
4007
- // src/utils/unified-error-handler/utils/ViteHMRDetector.ts
4008
- var ViteHMRDetector = class {
4009
- constructor(sendMessage) {
4010
- this.observer = null;
4011
- this.isInitialized = false;
4012
- this.sendMessage = sendMessage;
4013
- }
4014
- /**
4015
- * 初始化 Vite HMR 错误检测
4016
- */
4017
- initialize() {
4018
- if (this.isInitialized) return;
4019
- this.setupViteErrorDetection();
4020
- this.isInitialized = true;
4021
- }
4022
- /**
4023
- * 销毁检测器
4024
- */
4025
- destroy() {
4026
- if (this.observer) {
4027
- this.observer.disconnect();
4028
- this.observer = null;
4029
- }
4030
- this.isInitialized = false;
4031
- }
4032
- /**
4033
- * 设置 Vite 错误检测
4034
- */
4035
- setupViteErrorDetection() {
4036
- this.observer = new MutationObserver((mutations) => {
4037
- for (const mutation of mutations) {
4038
- if (mutation.addedNodes.length) {
4039
- const hasErrorOverlay = Array.from(mutation.addedNodes).some(
4040
- (node) => node.nodeName?.toLowerCase() === "vite-error-overlay"
4041
- );
4042
- if (hasErrorOverlay) {
4043
- requestAnimationFrame(() => this.checkForViteErrorOverlay());
4044
- }
4045
- }
4046
- }
4047
- });
4048
- this.observer.observe(document.body, {
4049
- childList: true,
4050
- subtree: true
4051
- });
4052
- this.setupHMREventListeners();
4053
- if (document.querySelector("vite-error-overlay")) {
4054
- requestAnimationFrame(() => this.checkForViteErrorOverlay());
4055
- }
4056
- }
4057
- /**
4058
- * 设置 HMR 事件监听器
4059
- */
4060
- setupHMREventListeners() {
4061
- if (typeof window !== "undefined" && window.import?.meta?.hot) {
4062
- const hot = window.import.meta.hot;
4063
- hot.on("vite:error", (data) => {
4064
- this.handleViteError(data);
4065
- requestAnimationFrame(() => this.checkForViteErrorOverlay());
4066
- });
4067
- hot.on("vite:invalidate", (data) => {
4068
- setTimeout(() => this.checkForCompileErrors(), 500);
4069
- });
4070
- hot.on("vite:beforeUpdate", () => {
4071
- });
4072
- hot.on("vite:afterUpdate", () => {
4073
- });
4074
- }
4075
- window.addEventListener("error", (event) => {
4076
- if (this.isViteRelatedError(event)) {
4077
- setTimeout(() => this.checkForViteErrorOverlay(), 100);
4078
- }
4079
- });
4080
- }
4081
- /**
4082
- * 检查是否是 Vite 相关错误
4083
- */
4084
- isViteRelatedError(event) {
4085
- const message = event.message?.toLowerCase() || "";
4086
- const filename = event.filename?.toLowerCase() || "";
4087
- return message.includes("vite") || message.includes("hmr") || filename.includes("vite") || filename.includes("@vite") || filename.includes("node_modules/vite");
4088
- }
4089
- /**
4090
- * 检查并处理 Vite 错误覆盖层
4091
- */
4092
- checkForViteErrorOverlay() {
4093
- const errorOverlay = document.querySelector("vite-error-overlay");
4094
- if (!errorOverlay) return;
4095
- if (!errorOverlay.shadowRoot) {
4096
- requestAnimationFrame(() => this.checkForViteErrorOverlay());
4097
- return;
4098
- }
4099
- try {
4100
- const errorInfo = this.extractErrorInfo(errorOverlay.shadowRoot);
4101
- const errorPayload = this.createErrorPayload(errorInfo);
4102
- if (window.__AUTO_ENGINEER_ERRORS__) {
4103
- window.__AUTO_ENGINEER_ERRORS__.push(errorPayload);
4104
- }
4105
- this.sendMessage({
4106
- type: "SYSTEM_EVENT",
4107
- payload: errorPayload,
4108
- timestamp: Date.now()
4109
- });
4110
- } catch (err) {
4111
- this.handleFallbackError(errorOverlay, err);
4112
- }
4113
- }
4114
- /**
4115
- * 从 Shadow DOM 中提取错误信息
4116
- */
4117
- extractErrorInfo(shadowRoot) {
4118
- const errorInfo = {};
4119
- errorInfo.plugin = shadowRoot.querySelector("span.plugin")?.textContent?.trim() || "";
4120
- errorInfo.messageBody = shadowRoot.querySelector(".message-body")?.textContent?.trim() || "";
4121
- errorInfo.fileText = shadowRoot.querySelector(".file")?.textContent?.trim() || "";
4122
- errorInfo.frame = shadowRoot.querySelector(".frame")?.textContent?.trim() || "";
4123
- errorInfo.stack = shadowRoot.querySelector(".stack")?.textContent?.trim() || "";
4124
- if (!errorInfo.messageBody) {
4125
- const messageElem = shadowRoot.querySelector(".message");
4126
- errorInfo.messageBody = messageElem?.textContent?.trim() || "";
4127
- }
4128
- if (!errorInfo.messageBody) {
4129
- const windowElem = shadowRoot.querySelector(".window");
4130
- errorInfo.messageBody = windowElem?.textContent?.trim() || "";
4131
- }
4132
- errorInfo.locationInfo = this.extractLocationInfo(errorInfo);
4133
- return errorInfo;
4134
- }
4135
- /**
4136
- * 提取文件位置信息
4137
- */
4138
- extractLocationInfo(errorInfo) {
4139
- const locationPatterns = [
4140
- // 从 file 元素提取
4141
- errorInfo.fileText?.match(/(.*?):(\d+):(\d+)/),
4142
- // 从 frame 文本提取
4143
- errorInfo.frame?.match(/(\S+\.[tj]sx?):(\d+):(\d+)/),
4144
- // 从消息文本提取
4145
- errorInfo.messageBody?.match(/([^:\s]+\.[tj]sx?):(\d+):(\d+)/)
4146
- ].filter(Boolean);
4147
- for (const match of locationPatterns) {
4148
- if (match && match.length >= 4) {
4149
- return {
4150
- filename: match[1],
4151
- line: parseInt(match[2], 10),
4152
- column: parseInt(match[3], 10)
4153
- };
4154
- }
4155
- }
4156
- return void 0;
4157
- }
4158
- /**
4159
- * 创建错误载荷
4160
- */
4161
- createErrorPayload(errorInfo) {
4162
- let fullErrorMessage = "";
4163
- if (errorInfo.plugin) {
4164
- fullErrorMessage += `[${errorInfo.plugin}] `;
4165
- }
4166
- fullErrorMessage += errorInfo.messageBody || "Unknown Vite error";
4167
- if (errorInfo.frame && !fullErrorMessage.includes(errorInfo.frame)) {
4168
- fullErrorMessage += `
4169
-
4170
- ${errorInfo.frame}`;
4171
- }
4172
- if (errorInfo.fileText && !fullErrorMessage.includes(errorInfo.fileText)) {
4173
- fullErrorMessage += `
4174
-
4175
- File: ${errorInfo.fileText}`;
4176
- }
4177
- const errorId = `hmr-error-${Date.now()}`;
4178
- return {
4179
- message: fullErrorMessage,
4180
- stack: errorInfo.stack || "",
4181
- filename: errorInfo.locationInfo?.filename,
4182
- lineno: errorInfo.locationInfo?.line,
4183
- colno: errorInfo.locationInfo?.column,
4184
- timestamp: Date.now(),
4185
- type: "vite_hmr",
4186
- severity: "high",
4187
- category: "development",
4188
- userAgent: navigator.userAgent,
4189
- url: window.location.href,
4190
- userInteractions: [...window.__AUTO_ENGINEER_INTERACTION_TRAIL__ || []],
4191
- details: {
4192
- source: "hmr",
4193
- errorId,
4194
- viteErrorInfo: DeepSerializer.quickSerialize(errorInfo),
4195
- pageUrl: window.location.href,
4196
- pagePath: window.location.pathname + window.location.search + window.location.hash
4197
- }
4198
- };
4199
- }
4200
- /**
4201
- * 降级错误处理
4202
- */
4203
- handleFallbackError(errorOverlay, originalError) {
4204
- try {
4205
- const anyText = errorOverlay.shadowRoot?.textContent?.trim() || "Unknown Vite error";
4206
- const errorPayload = {
4207
- message: `Vite error: ${anyText.substring(0, 500)}`,
4208
- stack: "",
4209
- timestamp: Date.now(),
4210
- type: "vite_hmr",
4211
- severity: "medium",
4212
- category: "development",
4213
- userAgent: navigator.userAgent,
4214
- url: window.location.href,
4215
- userInteractions: [...window.__AUTO_ENGINEER_INTERACTION_TRAIL__ || []],
4216
- details: {
4217
- source: "hmr-fallback",
4218
- errorId: `hmr-error-fallback-${Date.now()}`,
4219
- originalError: originalError?.message,
4220
- pageUrl: window.location.href,
4221
- pagePath: window.location.pathname + window.location.search + window.location.hash
4222
- }
4223
- };
4224
- if (window.__AUTO_ENGINEER_ERRORS__) {
4225
- window.__AUTO_ENGINEER_ERRORS__.push(errorPayload);
4226
- }
4227
- this.sendMessage({
4228
- type: "SYSTEM_EVENT",
4229
- payload: errorPayload,
4230
- timestamp: Date.now()
4231
- });
4232
- const originalConsole = window.__originalConsole;
4233
- if (originalConsole?.warn) {
4234
- originalConsole.warn("[ViteHMRDetector] \u4F7F\u7528\u964D\u7EA7\u65B9\u5F0F\u5904\u7406 Vite \u9519\u8BEF:", errorPayload);
4235
- }
4236
- } catch (finalErr) {
4237
- const originalConsole = window.__originalConsole;
4238
- if (originalConsole?.error) {
4239
- originalConsole.error("[ViteHMRDetector] \u65E0\u6CD5\u5904\u7406 Vite \u9519\u8BEF:", finalErr);
4240
- }
4241
- }
4242
- }
4243
- /**
4244
- * 处理 Vite 错误事件
4245
- */
4246
- handleViteError(errorData) {
4247
- try {
4248
- const errorPayload = {
4249
- id: `vite-error-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
4250
- type: "vite_hmr",
4251
- error: {
4252
- name: "ViteError",
4253
- message: errorData?.message || "Vite error",
4254
- stack: errorData?.stack || ""
4255
- },
4256
- source: "vite:error",
4257
- timestamp: Date.now(),
4258
- severity: "error",
4259
- context: {
4260
- viteErrorData: errorData,
4261
- url: window.location.href,
4262
- userAgent: navigator.userAgent
4263
- }
4264
- };
4265
- if (window.__AUTO_ENGINEER_ERRORS__) {
4266
- window.__AUTO_ENGINEER_ERRORS__.push(errorPayload);
4267
- }
4268
- this.sendMessage({
4269
- type: "SYSTEM_EVENT",
4270
- payload: errorPayload,
4271
- timestamp: Date.now()
4272
- });
4273
- } catch (error) {
4274
- console.error("[ViteHMRDetector] \u5904\u7406 Vite \u9519\u8BEF\u5931\u8D25:", error);
4275
- }
4276
- }
4277
- /**
4278
- * 检查编译错误
4279
- */
4280
- async checkForCompileErrors() {
4281
- try {
4282
- if (document.querySelector("vite-error-overlay")) {
4283
- this.checkForViteErrorOverlay();
4284
- return;
4285
- }
4286
- const response = await fetch(window.location.href, {
4287
- method: "HEAD",
4288
- cache: "no-cache"
4289
- });
4290
- if (!response.ok) {
4291
- this.handleCompileError(`HTTP ${response.status}: ${response.statusText}`);
4292
- }
4293
- } catch (error) {
4294
- this.handleCompileError(`Error: ${error.message}`);
4295
- }
4296
- }
4297
- /**
4298
- * 处理编译错误
4299
- */
4300
- handleCompileError(errorMessage) {
4301
- const errorPayload = {
4302
- id: `compile-error-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
4303
- type: "compile_error",
4304
- error: {
4305
- name: "CompileError",
4306
- message: `Compile error: ${errorMessage}`,
4307
- stack: ""
4308
- },
4309
- source: "vite:compile",
4310
- timestamp: Date.now(),
4311
- severity: "error",
4312
- context: {
4313
- url: window.location.href,
4314
- userAgent: navigator.userAgent,
4315
- compilationFailed: true
4316
- }
4317
- };
4318
- if (window.__AUTO_ENGINEER_ERRORS__) {
4319
- window.__AUTO_ENGINEER_ERRORS__.push(errorPayload);
4320
- }
4321
- this.sendMessage({
4322
- type: "SYSTEM_EVENT",
4323
- payload: errorPayload,
4324
- timestamp: Date.now()
4325
- });
4326
- }
4327
- /**
4328
- * 检查当前环境是否支持 Vite HMR
4329
- */
4330
- static isViteEnvironment() {
4331
- return !!(typeof window !== "undefined" && (window.import?.meta?.hot || window.__vite_plugin_react_preamble_installed__ || document.querySelector('script[type="module"][src*="vite"]') || document.querySelector('script[src*="@vite"]')));
4332
- }
4333
- };
4334
-
4335
- // src/utils/unified-error-handler/utils/HardRefreshManager.ts
4336
- var HardRefreshManager = class {
4337
- constructor(allowedOrigins = ["https://howone.ai", "http://localhost:3000"]) {
4338
- this.allowedOrigins = allowedOrigins;
4339
- this.setupMessageListener();
4340
- }
4341
- /**
4342
- * 设置消息监听器
4343
- */
4344
- setupMessageListener() {
4345
- window.addEventListener("message", async (event) => {
4346
- if (!this.isOriginAllowed(event.origin)) {
4347
- return;
4348
- }
4349
- if (event.data?.type === "HARD_REFRESH") {
4350
- await this.performHardRefresh(event.data.payload || {});
4351
- }
4352
- });
4353
- }
4354
- /**
4355
- * 检查来源是否被允许
4356
- */
4357
- isOriginAllowed(origin) {
4358
- return this.allowedOrigins.some(
4359
- (allowedOrigin) => origin.includes(allowedOrigin.replace("https://", "").replace("http://", ""))
4360
- );
4361
- }
4362
- /**
4363
- * 执行硬刷新
4364
- */
4365
- async performHardRefresh(options = {}) {
4366
- const defaultOptions = {
4367
- clearCaches: true,
4368
- unregisterServiceWorkers: true,
4369
- clearSessionStorage: true,
4370
- clearLocalStorage: false,
4371
- // 默认不清除 localStorage,可能包含重要应用数据
4372
- cacheBusting: true,
4373
- ...options
4374
- };
4375
- const result = {
4376
- success: false,
4377
- clearedCaches: [],
4378
- unregisteredWorkers: 0,
4379
- clearedStorage: []
4380
- };
4381
- try {
4382
- if (defaultOptions.clearCaches) {
4383
- const clearedCaches = await this.clearAllCaches();
4384
- result.clearedCaches = clearedCaches;
4385
- }
4386
- if (defaultOptions.unregisterServiceWorkers) {
4387
- const unregisteredCount = await this.unregisterServiceWorkers();
4388
- result.unregisteredWorkers = unregisteredCount;
4389
- }
4390
- const clearedStorage = await this.clearStorage(defaultOptions);
4391
- result.clearedStorage = clearedStorage;
4392
- await this.forceReload(defaultOptions);
4393
- result.success = true;
4394
- return result;
4395
- } catch (error) {
4396
- console.error("[HardRefreshManager] \u786C\u5237\u65B0\u5931\u8D25:", error);
4397
- result.error = error instanceof Error ? error.message : String(error);
4398
- await this.fallbackReload(defaultOptions);
4399
- return result;
4400
- }
4401
- }
4402
- /**
4403
- * 清除所有缓存
4404
- */
4405
- async clearAllCaches() {
4406
- const clearedCaches = [];
4407
- if ("caches" in window) {
4408
- try {
4409
- const cacheNames = await caches.keys();
4410
- await Promise.all(
4411
- cacheNames.map(async (cacheName) => {
4412
- try {
4413
- await caches.delete(cacheName);
4414
- clearedCaches.push(cacheName);
4415
- } catch (error) {
4416
- console.warn(`[HardRefreshManager] \u65E0\u6CD5\u5220\u9664\u7F13\u5B58 ${cacheName}:`, error);
4417
- }
4418
- })
4419
- );
4420
- } catch (error) {
4421
- console.warn("[HardRefreshManager] \u7F13\u5B58\u6E05\u7406\u5931\u8D25:", error);
4422
- }
4423
- }
4424
- return clearedCaches;
4425
- }
4426
- /**
4427
- * 注销所有 Service Workers
4428
- */
4429
- async unregisterServiceWorkers() {
4430
- let unregisteredCount = 0;
4431
- if ("serviceWorker" in navigator) {
4432
- try {
4433
- const registrations = await navigator.serviceWorker.getRegistrations();
4434
- await Promise.all(
4435
- registrations.map(async (registration) => {
4436
- try {
4437
- await registration.unregister();
4438
- unregisteredCount++;
4439
- } catch (error) {
4440
- console.warn("[HardRefreshManager] \u65E0\u6CD5\u6CE8\u9500 Service Worker:", error);
4441
- }
4442
- })
4443
- );
4444
- } catch (error) {
4445
- console.warn("[HardRefreshManager] Service Worker \u6CE8\u9500\u5931\u8D25:", error);
4446
- }
4447
- }
4448
- return unregisteredCount;
4449
- }
4450
- /**
4451
- * 清除存储
4452
- */
4453
- async clearStorage(options) {
4454
- const clearedStorage = [];
4455
- if (options.clearSessionStorage) {
4456
- try {
4457
- sessionStorage.clear();
4458
- clearedStorage.push("sessionStorage");
4459
- } catch (error) {
4460
- console.warn("[HardRefreshManager] \u65E0\u6CD5\u6E05\u9664 sessionStorage:", error);
4461
- }
4462
- }
4463
- if (options.clearLocalStorage) {
4464
- try {
4465
- localStorage.clear();
4466
- clearedStorage.push("localStorage");
4467
- } catch (error) {
4468
- console.warn("[HardRefreshManager] \u65E0\u6CD5\u6E05\u9664 localStorage:", error);
4469
- }
4470
- }
4471
- try {
4472
- await this.clearIndexedDB();
4473
- clearedStorage.push("indexedDB");
4474
- } catch (error) {
4475
- console.warn("[HardRefreshManager] IndexedDB \u6E05\u7406\u5931\u8D25:", error);
4476
- }
4477
- return clearedStorage;
4478
- }
4479
- /**
4480
- * 清除 IndexedDB
4481
- */
4482
- async clearIndexedDB() {
4483
- if ("indexedDB" in window) {
4484
- try {
4485
- if ("databases" in indexedDB) {
4486
- const databases = await indexedDB.databases();
4487
- await Promise.all(
4488
- databases.map(async (db) => {
4489
- return new Promise((resolve, reject) => {
4490
- const deleteReq = indexedDB.deleteDatabase(db.name);
4491
- deleteReq.onsuccess = () => resolve();
4492
- deleteReq.onerror = () => reject(deleteReq.error);
4493
- });
4494
- })
4495
- );
4496
- }
4497
- } catch (error) {
4498
- console.debug("[HardRefreshManager] IndexedDB \u6E05\u7406\u8DF3\u8FC7:", error);
4499
- }
4500
- }
4501
- }
4502
- /**
4503
- * 强制重载页面
4504
- */
4505
- async forceReload(options) {
4506
- const url = new URL(window.location.href);
4507
- if (options.cacheBusting) {
4508
- const token = options.token || Date.now();
4509
- url.searchParams.set("hard", String(token));
4510
- url.searchParams.set("_t", String(Date.now()));
4511
- }
4512
- window.location.replace(url.toString());
4513
- }
4514
- /**
4515
- * 降级重载(当硬刷新失败时)
4516
- */
4517
- async fallbackReload(options) {
4518
- try {
4519
- if (options.cacheBusting) {
4520
- const url = new URL(window.location.href);
4521
- url.searchParams.set("fallback", String(Date.now()));
4522
- window.location.replace(url.toString());
4523
- } else {
4524
- window.location.reload();
4525
- }
4526
- } catch (error) {
4527
- console.error("[HardRefreshManager] \u964D\u7EA7\u91CD\u8F7D\u4E5F\u5931\u8D25\u4E86:", error);
4528
- window.location.href = window.location.href;
4529
- }
4530
- }
4531
- /**
4532
- * 检查是否需要硬刷新
4533
- */
4534
- static shouldPerformHardRefresh() {
4535
- const url = new URL(window.location.href);
4536
- return url.searchParams.has("hard") || url.searchParams.has("force-refresh");
4537
- }
4538
- /**
4539
- * 清理 URL 中的硬刷新参数
4540
- */
4541
- static cleanupRefreshParams() {
4542
- const url = new URL(window.location.href);
4543
- const paramsToRemove = ["hard", "force-refresh", "_t", "fallback"];
4544
- let hasChanges = false;
4545
- paramsToRemove.forEach((param) => {
4546
- if (url.searchParams.has(param)) {
4547
- url.searchParams.delete(param);
4548
- hasChanges = true;
4549
- }
4550
- });
4551
- if (hasChanges) {
4552
- window.history.replaceState({}, document.title, url.toString());
4553
- }
4554
- }
4555
- /**
4556
- * 获取刷新统计信息
4557
- */
4558
- static getRefreshStats() {
4559
- const url = new URL(window.location.href);
4560
- const hardParam = url.searchParams.get("hard");
4561
- const timestampParam = url.searchParams.get("_t");
4562
- return {
4563
- isHardRefresh: !!hardParam,
4564
- refreshToken: hardParam || void 0,
4565
- timestamp: timestampParam ? parseInt(timestampParam, 10) : void 0
4566
- };
4567
- }
4568
- };
4569
-
4570
- // src/utils/unified-error-handler/utils/ViewDetector.ts
4571
- var ViewDetector = class {
4572
- constructor(config) {
4573
- this.cache = {
4574
- value: null,
4575
- timestamp: 0
4576
- };
4577
- this.config = {
4578
- cacheTimeout: 100,
4579
- // 100ms 缓存
4580
- semanticKeywords: [
4581
- "dashboard",
4582
- "profile",
4583
- "settings",
4584
- "admin",
4585
- "login",
4586
- "signup",
4587
- "home",
4588
- "about",
4589
- "contact",
4590
- "help",
4591
- "account",
4592
- "billing",
4593
- "reports",
4594
- "analytics",
4595
- "users",
4596
- "projects",
4597
- "tasks",
4598
- "invoice",
4599
- "orders",
4600
- "products",
4601
- "customers",
4602
- "payments",
4603
- "notifications",
4604
- "workspace",
4605
- "editor",
4606
- "preview",
4607
- "gallery",
4608
- "search",
4609
- "results",
4610
- "details",
4611
- "form",
4612
- "wizard",
4613
- "checkout",
4614
- "cart"
4615
- ],
4616
- genericTitles: ["loading", "my app", "localhost", "app", "untitled", "new tab"],
4617
- explicitMarkers: [
4618
- { selector: "[data-page]", attr: "data-page" },
4619
- { selector: "[data-view]", attr: "data-view" },
4620
- { selector: "[data-route]", attr: "data-route" },
4621
- { selector: '[data-testid*="page"]', attr: "data-testid" },
4622
- { selector: '[data-testid*="view"]', attr: "data-testid" },
4623
- { selector: '[data-testid*="screen"]', attr: "data-testid" }
4624
- ],
4625
- classPatterns: [
4626
- /(?:page|view|screen)-([a-zA-Z]+)/i,
4627
- /([a-zA-Z]+)(?:Page|View|Screen)$/i,
4628
- /route-([a-zA-Z]+)/i,
4629
- /([a-zA-Z]+)-route/i
4630
- ]
4631
- };
4632
- if (config) {
4633
- this.config = { ...this.config, ...config };
4634
- }
4635
- }
4636
- /**
4637
- * 检测当前视图
4638
- */
4639
- detectCurrentView() {
4640
- const now = Date.now();
4641
- if (this.cache.value && now - this.cache.timestamp < this.config.cacheTimeout) {
4642
- return this.cache.value;
4643
- }
4644
- const result = this.performDetection();
4645
- this.cache = { value: result, timestamp: now };
4646
- return result;
4647
- }
4648
- /**
4649
- * 执行检测
4650
- */
4651
- performDetection() {
4652
- const strategies = [
4653
- () => this.detectByTitle(),
4654
- () => this.detectByMainHeading(),
4655
- () => this.detectByActiveNavigation(),
4656
- () => this.detectByExplicitMarkers(),
4657
- () => this.detectByMainContent(),
4658
- () => this.detectByURL(),
4659
- () => this.detectByMetaTags(),
4660
- () => this.detectByBreadcrumbs()
4661
- ];
4662
- for (const strategy of strategies) {
4663
- const result = strategy();
4664
- if (result && result.confidence > 0.5) {
4665
- return this.enrichResult(result);
4666
- }
4667
- }
4668
- return this.enrichResult({
4669
- title: "Unknown View",
4670
- confidence: 0.1,
4671
- strategy: "fallback",
4672
- timestamp: Date.now(),
4673
- url: window.location.href
4674
- });
4675
- }
4676
- /**
4677
- * 通过文档标题检测
4678
- */
4679
- detectByTitle() {
4680
- const title = document.title?.trim();
4681
- if (!title || this.isGenericTitle(title)) {
4682
- return null;
4683
- }
4684
- return {
4685
- title: this.cleanTitle(title),
4686
- confidence: 0.8,
4687
- strategy: "document-title",
4688
- timestamp: Date.now(),
4689
- url: window.location.href
4690
- };
4691
- }
4692
- /**
4693
- * 通过主标题检测
4694
- */
4695
- detectByMainHeading() {
4696
- const headings = document.querySelectorAll(
4697
- 'h1:not([style*="display: none"]):not([hidden]), h2:not([style*="display: none"]):not([hidden])'
4698
- );
4699
- for (const heading of headings) {
4700
- if (this.isElementVisible(heading) && heading.textContent?.trim()) {
4701
- const text = heading.textContent.trim();
4702
- if (text.length > 2 && text.length < 100) {
4703
- return {
4704
- title: text,
4705
- confidence: 0.7,
4706
- strategy: "main-heading",
4707
- timestamp: Date.now(),
4708
- url: window.location.href
4709
- };
4710
- }
4711
- }
4712
- }
4713
- return null;
4714
- }
4715
- /**
4716
- * 通过活动导航检测
4717
- */
4718
- detectByActiveNavigation() {
4719
- const activeNavSelectors = [
4720
- '[aria-current="page"]',
4721
- ".active:not(.disabled)",
4722
- ".current",
4723
- '[data-current="true"]',
4724
- ".router-link-active",
4725
- ".router-link-exact-active",
4726
- ".nav-link.active",
4727
- ".navbar-nav .active",
4728
- ".breadcrumb .active"
4729
- ];
4730
- for (const selector of activeNavSelectors) {
4731
- const activeNav = document.querySelector(selector);
4732
- if (activeNav && activeNav.textContent?.trim()) {
4733
- const text = activeNav.textContent.trim();
4734
- if (text.length > 1 && text.length < 50) {
4735
- return {
4736
- title: text,
4737
- confidence: 0.75,
4738
- strategy: "active-navigation",
4739
- timestamp: Date.now(),
4740
- url: window.location.href
4741
- };
4742
- }
4743
- }
4744
- }
4745
- return null;
4746
- }
4747
- /**
4748
- * 通过显式标记检测
4749
- */
4750
- detectByExplicitMarkers() {
4751
- for (const marker of this.config.explicitMarkers) {
4752
- const element = document.querySelector(marker.selector);
4753
- if (element) {
4754
- const value = element.getAttribute(marker.attr);
4755
- if (value && value.length > 0) {
4756
- return {
4757
- title: this.formatMarkerValue(value),
4758
- confidence: 0.9,
4759
- strategy: "explicit-markers",
4760
- timestamp: Date.now(),
4761
- url: window.location.href
4762
- };
4763
- }
4764
- }
4765
- }
4766
- for (const pattern of this.config.classPatterns) {
4767
- const elements = document.querySelectorAll(
4768
- '[class*="page-"], [class*="view-"], [class*="Page"], [class*="View"], [class*="Screen"], [class*="route"]'
4769
- );
4770
- for (const element of elements) {
4771
- const match = element.className.match(pattern);
4772
- if (match && match[1]) {
4773
- return {
4774
- title: this.formatMarkerValue(match[1]),
4775
- confidence: 0.8,
4776
- strategy: "class-patterns",
4777
- timestamp: Date.now(),
4778
- url: window.location.href
4779
- };
4780
- }
4781
- }
4782
- }
4783
- return null;
4784
- }
4785
- /**
4786
- * 通过主内容分析检测
4787
- */
4788
- detectByMainContent() {
4789
- const mainContainers = document.querySelectorAll(
4790
- 'main, [role="main"], .main-content, #main, .app-content, .page-content, .content'
4791
- );
4792
- for (const main of mainContainers) {
4793
- for (const keyword of this.config.semanticKeywords) {
4794
- const indicator = main.querySelector(`[class*="${keyword}"], [id*="${keyword}"]`);
4795
- if (indicator) {
4796
- return {
4797
- title: this.capitalizeFirst(keyword),
4798
- confidence: 0.6,
4799
- strategy: "main-content-semantic",
4800
- timestamp: Date.now(),
4801
- url: window.location.href
4802
- };
4803
- }
4804
- }
4805
- const titleElement = main.querySelector("h1, h2, .title, .page-title, .view-title");
4806
- if (titleElement && titleElement.textContent?.trim()) {
4807
- const text = titleElement.textContent.trim();
4808
- if (text.length > 2 && text.length < 100) {
4809
- return {
4810
- title: text,
4811
- confidence: 0.65,
4812
- strategy: "main-content-title",
4813
- timestamp: Date.now(),
4814
- url: window.location.href
4815
- };
4816
- }
4817
- }
4818
- }
4819
- return null;
4820
- }
4821
- /**
4822
- * 通过 URL 检测
4823
- */
4824
- detectByURL() {
4825
- const pathname = window.location.pathname;
4826
- if (!pathname || pathname === "/" || pathname === "/index.html") {
4827
- return null;
4828
- }
4829
- const segments = pathname.split("/").filter(Boolean);
4830
- if (segments.length === 0) {
4831
- return null;
4832
- }
4833
- const lastSegment = segments[segments.length - 1];
4834
- const cleanSegment = lastSegment.replace(/\.(html|php|jsp|asp)$/, "").replace(/-/g, " ").replace(/_/g, " ");
4835
- if (cleanSegment.length > 1) {
4836
- return {
4837
- title: this.capitalizeWords(cleanSegment),
4838
- confidence: 0.5,
4839
- strategy: "url-pathname",
4840
- timestamp: Date.now(),
4841
- url: window.location.href
4842
- };
4843
- }
4844
- return null;
4845
- }
4846
- /**
4847
- * 通过 Meta 标签检测
4848
- */
4849
- detectByMetaTags() {
4850
- const metaSelectors = [
4851
- 'meta[property="og:title"]',
4852
- 'meta[name="twitter:title"]',
4853
- 'meta[name="title"]',
4854
- 'meta[property="og:description"]'
4855
- ];
4856
- for (const selector of metaSelectors) {
4857
- const meta = document.querySelector(selector);
4858
- if (meta && meta.content?.trim()) {
4859
- const content = meta.content.trim();
4860
- if (!this.isGenericTitle(content) && content.length > 2 && content.length < 100) {
4861
- return {
4862
- title: content,
4863
- confidence: 0.6,
4864
- strategy: "meta-tags",
4865
- timestamp: Date.now(),
4866
- url: window.location.href
4867
- };
4868
- }
4869
- }
4870
- }
4871
- return null;
4872
- }
4873
- /**
4874
- * 通过面包屑检测
4875
- */
4876
- detectByBreadcrumbs() {
4877
- const breadcrumbSelectors = [
4878
- ".breadcrumb",
4879
- ".breadcrumbs",
4880
- '[aria-label="breadcrumb"]',
4881
- ".nav-breadcrumb"
4882
- ];
4883
- for (const selector of breadcrumbSelectors) {
4884
- const breadcrumb = document.querySelector(selector);
4885
- if (breadcrumb) {
4886
- const items = breadcrumb.querySelectorAll("li, a, span");
4887
- const lastItem = items[items.length - 1];
4888
- if (lastItem && lastItem.textContent?.trim()) {
4889
- const text = lastItem.textContent.trim();
4890
- if (text.length > 1 && text.length < 50) {
4891
- return {
4892
- title: text,
4893
- confidence: 0.7,
4894
- strategy: "breadcrumbs",
4895
- timestamp: Date.now(),
4896
- url: window.location.href
4897
- };
4898
- }
4899
- }
4900
- }
4901
- }
4902
- return null;
4903
- }
4904
- /**
4905
- * 丰富检测结果
4906
- */
4907
- enrichResult(result) {
4908
- return {
4909
- ...result,
4910
- viewport: {
4911
- width: window.innerWidth,
4912
- height: window.innerHeight
4913
- }
4914
- };
4915
- }
4916
- /**
4917
- * 检查是否为通用标题
4918
- */
4919
- isGenericTitle(title) {
4920
- const lowerTitle = title.toLowerCase();
4921
- return this.config.genericTitles.some(
4922
- (generic) => lowerTitle.includes(generic) || lowerTitle === generic
4923
- ) || title === document.location.hostname;
4924
- }
4925
- /**
4926
- * 检查元素是否可见
4927
- */
4928
- isElementVisible(element) {
4929
- const rect = element.getBoundingClientRect();
4930
- return rect.width > 0 && rect.height > 0;
4931
- }
4932
- /**
4933
- * 清理标题
4934
- */
4935
- cleanTitle(title) {
4936
- return title.replace(/\s*[-|–—]\s*.*$/, "").replace(/\s*\|\s*.*$/, "").trim();
4937
- }
4938
- /**
4939
- * 格式化标记值
4940
- */
4941
- formatMarkerValue(value) {
4942
- return value.replace(/[-_]/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").trim();
4943
- }
4944
- /**
4945
- * 首字母大写
4946
- */
4947
- capitalizeFirst(str) {
4948
- return str.charAt(0).toUpperCase() + str.slice(1);
4949
- }
4950
- /**
4951
- * 单词首字母大写
4952
- */
4953
- capitalizeWords(str) {
4954
- return str.replace(/\b\w/g, (char) => char.toUpperCase());
4955
- }
4956
- /**
4957
- * 获取当前视图信息
4958
- */
4959
- getCurrentViewInfo() {
4960
- const detection = this.detectCurrentView();
4961
- return {
4962
- title: detection.title,
4963
- url: detection.url,
4964
- timestamp: detection.timestamp,
4965
- viewport: detection.viewport
4966
- };
4967
- }
4968
- /**
4969
- * 清除缓存
4970
- */
4971
- clearCache() {
4972
- this.cache = { value: null, timestamp: 0 };
4973
- }
4974
- };
4975
-
4976
- // src/utils/unified-error-handler/utils/ComponentTreeGenerator.ts
4977
- var ComponentTreeGenerator = class {
4978
- constructor() {
4979
- this.config = {
4980
- maxDepth: 20,
4981
- includeHiddenElements: false,
4982
- includeTextNodes: true,
4983
- includeReactInfo: true,
4984
- minTextLength: 3,
4985
- excludeTagNames: ["script", "style", "meta", "link", "title", "head"],
4986
- includeAttributes: ["id", "class", "data-testid", "data-component-path", "aria-label", "title", "placeholder", "type", "name", "href", "src"],
4987
- maxTextLength: 100,
4988
- maxChildren: 50
4989
- };
4990
- }
4991
- /** ----------------- 主要生成方法 ----------------- */
4992
- /**
4993
- * 生成完整的组件树
4994
- */
4995
- generateComponentTree(rootElement) {
4996
- const startTime = Date.now();
4997
- const root = rootElement || document.body;
4998
- const rootNode = this.generateNodeTree(root, 0);
4999
- const stats = this.calculateTreeStats(rootNode);
5000
- const componentTree = {
5001
- root: rootNode,
5002
- totalNodes: stats.totalNodes,
5003
- maxDepth: stats.maxDepth,
5004
- interactiveNodes: stats.interactiveNodes,
5005
- visibleNodes: stats.visibleNodes,
5006
- generatedAt: Date.now(),
5007
- metadata: {
5008
- url: window.location.href,
5009
- title: document.title,
5010
- viewport: {
5011
- width: window.innerWidth,
5012
- height: window.innerHeight
5013
- },
5014
- framework: this.detectFramework()
5015
- }
5016
- };
5017
- const generationTime = Date.now() - startTime;
5018
- return componentTree;
5019
- }
5020
- /**
5021
- * 生成节点树
5022
- */
5023
- generateNodeTree(element, depth) {
5024
- if (depth > this.config.maxDepth) {
5025
- return this.createLeafNode(element, depth);
5026
- }
5027
- const node = {
5028
- id: this.generateNodeId(element, depth),
5029
- tagName: element.tagName.toLowerCase(),
5030
- className: element.className || void 0,
5031
- elementId: element.id || void 0,
5032
- textContent: this.getElementTextContent(element),
5033
- attributes: this.getElementAttributes(element),
5034
- children: [],
5035
- depth,
5036
- isVisible: this.isElementVisible(element),
5037
- isInteractive: this.isElementInteractive(element),
5038
- boundingRect: this.getElementBoundingRect(element),
5039
- reactInfo: this.config.includeReactInfo ? this.getReactInfo(element) : void 0
5040
- };
5041
- const children = Array.from(element.children);
5042
- const validChildren = children.filter((child) => this.shouldIncludeElement(child));
5043
- const childrenToProcess = validChildren.slice(0, this.config.maxChildren);
5044
- node.children = childrenToProcess.map(
5045
- (child) => this.generateNodeTree(child, depth + 1)
5046
- );
5047
- if (validChildren.length > this.config.maxChildren) {
5048
- node.children.push(this.createPlaceholderNode(
5049
- validChildren.length - this.config.maxChildren,
5050
- depth + 1
5051
- ));
5052
- }
5053
- return node;
5054
- }
5055
- /** ----------------- 节点创建辅助方法 ----------------- */
5056
- /**
5057
- * 创建叶子节点(达到最大深度时)
5058
- */
5059
- createLeafNode(element, depth) {
5060
- return {
5061
- id: this.generateNodeId(element, depth),
5062
- tagName: element.tagName.toLowerCase(),
5063
- className: element.className || void 0,
5064
- elementId: element.id || void 0,
5065
- textContent: "[Max depth reached]",
5066
- attributes: this.getElementAttributes(element),
5067
- children: [],
5068
- depth,
5069
- isVisible: this.isElementVisible(element),
5070
- isInteractive: this.isElementInteractive(element),
5071
- boundingRect: this.getElementBoundingRect(element)
5072
- };
5073
- }
5074
- /**
5075
- * 创建占位符节点(子元素过多时)
5076
- */
5077
- createPlaceholderNode(remainingCount, depth) {
5078
- return {
5079
- id: `placeholder-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
5080
- tagName: "placeholder",
5081
- textContent: `... and ${remainingCount} more children`,
5082
- attributes: {},
5083
- children: [],
5084
- depth,
5085
- isVisible: false,
5086
- isInteractive: false,
5087
- boundingRect: { x: 0, y: 0, width: 0, height: 0 }
5088
- };
5089
- }
5090
- /** ----------------- 元素信息提取方法 ----------------- */
5091
- /**
5092
- * 生成节点 ID
5093
- */
5094
- generateNodeId(element, depth) {
5095
- const timestamp = Date.now();
5096
- const random = Math.random().toString(36).substr(2, 9);
5097
- const tagName = element.tagName.toLowerCase();
5098
- const elementId = element.id ? `-${element.id}` : "";
5099
- return `${tagName}${elementId}-${depth}-${timestamp}-${random}`;
5100
- }
5101
- /**
5102
- * 获取元素文本内容
5103
- */
5104
- getElementTextContent(element) {
5105
- if (!this.config.includeTextNodes) return void 0;
5106
- const textNodes = Array.from(element.childNodes).filter((node) => node.nodeType === Node.TEXT_NODE).map((node) => node.textContent?.trim()).filter((text) => text && text.length >= this.config.minTextLength);
5107
- if (textNodes.length === 0) return void 0;
5108
- const fullText = textNodes.join(" ").trim();
5109
- return fullText.length > this.config.maxTextLength ? fullText.substring(0, this.config.maxTextLength) + "..." : fullText;
5110
- }
5111
- /**
5112
- * 获取元素属性
5113
- */
5114
- getElementAttributes(element) {
5115
- const attributes = {};
5116
- this.config.includeAttributes.forEach((attrName) => {
5117
- const value = element.getAttribute(attrName);
5118
- if (value) {
5119
- attributes[attrName] = value.length > 100 ? value.substring(0, 100) + "..." : value;
5120
- }
5121
- });
5122
- if (element instanceof HTMLInputElement) {
5123
- if (element.type) attributes.inputType = element.type;
5124
- if (element.placeholder) attributes.placeholder = element.placeholder;
5125
- }
5126
- if (element instanceof HTMLAnchorElement) {
5127
- if (element.href) attributes.href = element.href;
5128
- }
5129
- if (element instanceof HTMLImageElement) {
5130
- if (element.src) attributes.src = element.src;
5131
- if (element.alt) attributes.alt = element.alt;
5132
- }
5133
- return attributes;
5134
- }
5135
- /**
5136
- * 获取元素边界矩形
5137
- */
5138
- getElementBoundingRect(element) {
5139
- try {
5140
- const rect = element.getBoundingClientRect();
5141
- return {
5142
- x: Math.round(rect.left),
5143
- y: Math.round(rect.top),
5144
- width: Math.round(rect.width),
5145
- height: Math.round(rect.height)
5146
- };
5147
- } catch (error) {
5148
- return { x: 0, y: 0, width: 0, height: 0 };
5149
- }
5150
- }
5151
- /** ----------------- 元素状态检测方法 ----------------- */
5152
- /**
5153
- * 检查元素是否可见
5154
- */
5155
- isElementVisible(element) {
5156
- if (!this.config.includeHiddenElements) {
5157
- try {
5158
- const style = window.getComputedStyle(element);
5159
- if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") {
5160
- return false;
5161
- }
5162
- const rect = element.getBoundingClientRect();
5163
- return rect.width > 0 && rect.height > 0;
5164
- } catch (error) {
5165
- return false;
5166
- }
5167
- }
5168
- return true;
5169
- }
5170
- /**
5171
- * 检查元素是否可交互
5172
- */
5173
- isElementInteractive(element) {
5174
- const interactiveTags = ["button", "input", "select", "textarea", "a", "label"];
5175
- const tagName = element.tagName.toLowerCase();
5176
- if (interactiveTags.includes(tagName)) {
5177
- return true;
5178
- }
5179
- if (element.onclick || element.getAttribute("onclick") || element.hasAttribute("data-testid") || element.getAttribute("role") === "button") {
5180
- return true;
5181
- }
5182
- if (element.hasAttribute("tabindex")) {
5183
- return true;
5184
- }
5185
- return false;
5186
- }
5187
- /**
5188
- * 检查是否应该包含该元素
5189
- */
5190
- shouldIncludeElement(element) {
5191
- const tagName = element.tagName.toLowerCase();
5192
- if (this.config.excludeTagNames.includes(tagName)) {
5193
- return false;
5194
- }
5195
- if (!this.config.includeHiddenElements && !this.isElementVisible(element)) {
5196
- return false;
5197
- }
5198
- return true;
5199
- }
5200
- /** ----------------- React 信息提取方法 ----------------- */
5201
- /**
5202
- * 获取 React 组件信息
5203
- */
5204
- getReactInfo(element) {
5205
- try {
5206
- const fiberKey = Object.keys(element).find(
5207
- (key) => key.startsWith("__reactInternalInstance") || key.startsWith("__reactFiber")
5208
- );
5209
- if (fiberKey) {
5210
- const fiber = element[fiberKey];
5211
- return this.extractReactFiberInfo(fiber);
5212
- }
5213
- if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
5214
- return this.extractReactDevToolsInfo(element);
5215
- }
5216
- return void 0;
5217
- } catch (error) {
5218
- console.warn("[ComponentTreeGenerator] \u83B7\u53D6 React \u4FE1\u606F\u5931\u8D25:", error instanceof Error ? error.message : String(error));
5219
- return void 0;
5220
- }
5221
- }
5222
- /**
5223
- * 从 React Fiber 提取信息
5224
- */
5225
- extractReactFiberInfo(fiber) {
5226
- if (!fiber) return void 0;
5227
- try {
5228
- const componentName = fiber.type?.name || fiber.type?.displayName || fiber.elementType?.name || "Unknown";
5229
- const props = fiber.memoizedProps ? this.sanitizeReactData(fiber.memoizedProps) : void 0;
5230
- const state = fiber.memoizedState ? this.sanitizeReactData(fiber.memoizedState) : void 0;
5231
- return {
5232
- componentName,
5233
- props,
5234
- state
5235
- };
5236
- } catch (error) {
5237
- return void 0;
5238
- }
5239
- }
5240
- /**
5241
- * 从 React DevTools 提取信息
5242
- */
5243
- extractReactDevToolsInfo(_element) {
5244
- return void 0;
5245
- }
5246
- /**
5247
- * 清理 React 数据(移除敏感信息)
5248
- */
5249
- sanitizeReactData(data) {
5250
- if (!data || typeof data !== "object") {
5251
- return data;
5252
- }
5253
- const sanitized = {};
5254
- const maxKeys = 10;
5255
- let keyCount = 0;
5256
- for (const [key, value] of Object.entries(data)) {
5257
- if (keyCount >= maxKeys) break;
5258
- if (key.startsWith("_") || key === "children" || typeof value === "function") {
5259
- continue;
5260
- }
5261
- if (typeof value === "object" && value !== null) {
5262
- sanitized[key] = "[Object]";
5263
- } else {
5264
- sanitized[key] = String(value).substring(0, 50);
5265
- }
5266
- keyCount++;
5267
- }
5268
- return sanitized;
5269
- }
5270
- /** ----------------- 框架检测方法 ----------------- */
5271
- /**
5272
- * 检测前端框架
5273
- */
5274
- detectFramework() {
5275
- if (window.React || document.querySelector("[data-reactroot]") || document.querySelector("#root")) {
5276
- return "React";
5277
- }
5278
- if (window.Vue || document.querySelector("[data-v-]") || document.querySelector("#app")) {
5279
- return "Vue";
5280
- }
5281
- if (window.ng || document.querySelector("[ng-app]") || document.querySelector("app-root")) {
5282
- return "Angular";
5283
- }
5284
- if (document.querySelector("[data-svelte]")) {
5285
- return "Svelte";
5286
- }
5287
- return void 0;
5288
- }
5289
- /** ----------------- 统计计算方法 ----------------- */
5290
- /**
5291
- * 计算树统计信息
5292
- */
5293
- calculateTreeStats(rootNode) {
5294
- let totalNodes = 0;
5295
- let maxDepth = 0;
5296
- let interactiveNodes = 0;
5297
- let visibleNodes = 0;
5298
- const traverse = (node) => {
5299
- totalNodes++;
5300
- maxDepth = Math.max(maxDepth, node.depth);
5301
- if (node.isInteractive) interactiveNodes++;
5302
- if (node.isVisible) visibleNodes++;
5303
- node.children.forEach((child) => traverse(child));
5304
- };
5305
- traverse(rootNode);
5306
- return {
5307
- totalNodes,
5308
- maxDepth,
5309
- interactiveNodes,
5310
- visibleNodes
5311
- };
5312
- }
5313
- /** ----------------- 公共接口方法 ----------------- */
5314
- /**
5315
- * 生成指定元素的组件树
5316
- */
5317
- generateElementTree(elementId) {
5318
- const element = document.getElementById(elementId);
5319
- if (!element) {
5320
- console.warn(`[ComponentTreeGenerator] \u672A\u627E\u5230\u5143\u7D20: ${elementId}`);
5321
- return null;
5322
- }
5323
- return this.generateComponentTree(element);
5324
- }
5325
- /**
5326
- * 生成可见元素的组件树
5327
- */
5328
- generateVisibleTree() {
5329
- const originalConfig = { ...this.config };
5330
- this.config.includeHiddenElements = false;
5331
- const tree = this.generateComponentTree();
5332
- this.config = originalConfig;
5333
- return tree;
5334
- }
5335
- /**
5336
- * 查找组件节点
5337
- */
5338
- findNodeById(tree, nodeId) {
5339
- const search = (node) => {
5340
- if (node.id === nodeId) return node;
5341
- for (const child of node.children) {
5342
- const found = search(child);
5343
- if (found) return found;
5344
- }
5345
- return null;
5346
- };
5347
- return search(tree.root);
5348
- }
5349
- /**
5350
- * 查找交互元素
5351
- */
5352
- findInteractiveNodes(tree) {
5353
- const interactiveNodes = [];
5354
- const traverse = (node) => {
5355
- if (node.isInteractive) {
5356
- interactiveNodes.push(node);
5357
- }
5358
- node.children.forEach((child) => traverse(child));
5359
- };
5360
- traverse(tree.root);
5361
- return interactiveNodes;
5362
- }
5363
- /**
5364
- * 更新配置
5365
- */
5366
- updateConfig(newConfig) {
5367
- this.config = { ...this.config, ...newConfig };
5368
- }
5369
- /**
5370
- * 获取当前配置
5371
- */
5372
- getConfig() {
5373
- return { ...this.config };
5374
- }
5375
- /**
5376
- * 导出组件树为 JSON
5377
- */
5378
- exportTreeAsJSON(tree) {
5379
- try {
5380
- return JSON.stringify(tree, null, 2);
5381
- } catch (error) {
5382
- console.error("[ComponentTreeGenerator] \u5BFC\u51FA JSON \u5931\u8D25:", error instanceof Error ? error.message : String(error));
5383
- return "{}";
5384
- }
5385
- }
5386
- /**
5387
- * 销毁生成器
5388
- */
5389
- destroy() {
5390
- }
5391
- };
5392
-
5393
- // src/utils/unified-error-handler/utils/MessageSender.ts
5394
- var getOriginalConsole = () => window.__originalConsole || {
5395
- log: console.log.bind(console),
5396
- warn: console.warn.bind(console),
5397
- error: console.error.bind(console),
5398
- info: console.info.bind(console),
5399
- debug: console.debug.bind(console)
5400
- };
5401
- var MessageSender = class {
5402
- constructor(options = {}) {
5403
- this.options = {
5404
- addTimestamp: true,
5405
- enableDebugLog: false,
5406
- allowedOrigins: GLOBAL_CONFIG.ALLOWED_ORIGINS,
5407
- ...options
5408
- };
5409
- }
5410
- /**
5411
- * 发送消息到父窗口
5412
- */
5413
- send(message) {
5414
- try {
5415
- if (!this.isInIframe()) {
5416
- if (this.options.enableDebugLog) {
5417
- const originalConsole = getOriginalConsole();
5418
- originalConsole.debug("[MessageSender] \u4E0D\u5728 iframe \u4E2D\uFF0C\u8DF3\u8FC7\u53D1\u9001");
5419
- }
5420
- return false;
5421
- }
5422
- const finalMessage = this.prepareMessage(message);
5423
- const success = this.sendToParent(finalMessage);
5424
- if (this.options.enableDebugLog) {
5425
- const originalConsole = getOriginalConsole();
5426
- originalConsole.debug("[MessageSender] \u53D1\u9001\u6D88\u606F:", finalMessage, "\u6210\u529F:", success);
5427
- }
5428
- return success;
5429
- } catch (error) {
5430
- this.handleError("\u53D1\u9001\u6D88\u606F\u5931\u8D25", error);
5431
- return false;
5432
- }
5433
- }
5434
- /**
5435
- * 创建发送函数(用于注入到其他模块)
5436
- */
5437
- createSendFunction() {
5438
- return (message) => {
5439
- this.send(message);
5440
- };
5441
- }
5442
- /**
5443
- * 检查是否在 iframe 中
5444
- */
5445
- isInIframe() {
5446
- return window.parent && window.parent !== window;
5447
- }
5448
- /**
5449
- * 准备消息(添加时间戳等)
5450
- */
5451
- prepareMessage(message) {
5452
- if (!this.options.addTimestamp) {
5453
- return message;
5454
- }
5455
- return {
5456
- ...message,
5457
- timestamp: Date.now()
5458
- };
5459
- }
5460
- /**
5461
- * 发送消息到父窗口
5462
- */
5463
- sendToParent(message) {
5464
- try {
5465
- const isLocalhost = this.isLocalhostEnvironment();
5466
- if (isLocalhost) {
5467
- window.parent.postMessage(message, "*");
5468
- return true;
5469
- } else {
5470
- return this.tryMultipleOrigins(message);
5471
- }
5472
- } catch (error) {
5473
- this.handleError("postMessage \u8C03\u7528\u5931\u8D25", error);
5474
- return false;
5475
- }
5476
- }
5477
- /**
5478
- * 检测是否为本地环境
5479
- */
5480
- isLocalhostEnvironment() {
5481
- const origin = window.location.origin;
5482
- return origin.includes("localhost") || origin.includes("127.0.0.1") || origin.includes("0.0.0.0");
5483
- }
5484
- /**
5485
- * 尝试多个源发送消息
5486
- */
5487
- tryMultipleOrigins(message) {
5488
- let messageSent = false;
5489
- for (const origin of this.options.allowedOrigins) {
5490
- try {
5491
- window.parent.postMessage(message, origin);
5492
- messageSent = true;
5493
- break;
5494
- } catch (error) {
5495
- continue;
5496
- }
5497
- }
5498
- if (!messageSent) {
5499
- try {
5500
- window.parent.postMessage(message, "*");
5501
- messageSent = true;
5502
- } catch (error) {
5503
- this.handleError("\u901A\u914D\u7B26\u53D1\u9001\u4E5F\u5931\u8D25", error);
5504
- }
5505
- }
5506
- return messageSent;
5507
- }
5508
- /**
5509
- * 处理错误
5510
- */
5511
- handleError(context, error) {
5512
- const originalConsole = getOriginalConsole();
5513
- originalConsole.debug(`[MessageSender] ${context}:`, error);
5514
- }
5515
- /**
5516
- * 更新配置
5517
- */
5518
- updateOptions(newOptions) {
5519
- this.options = {
5520
- ...this.options,
5521
- ...newOptions
5522
- };
5523
- }
5524
- /**
5525
- * 获取当前配置
5526
- */
5527
- getOptions() {
5528
- return { ...this.options };
5529
- }
5530
- };
5531
- var createDefaultMessageSender = (options) => {
5532
- return new MessageSender({
5533
- addTimestamp: true,
5534
- enableDebugLog: false,
5535
- ...options
5536
- });
5537
- };
5538
- var createSimpleSendFunction = (options) => {
5539
- const sender = createDefaultMessageSender(options);
5540
- return sender.createSendFunction();
5541
- };
5542
-
5543
- // src/utils/unified-error-handler/features/ErrorTracking.ts
5544
- var ORIGINAL_CONSOLE = {
5545
- log: console.log.bind(console),
5546
- warn: console.warn.bind(console),
5547
- error: console.error.bind(console),
5548
- info: console.info.bind(console),
5549
- debug: console.debug.bind(console)
5550
- };
5551
- window.__originalConsole = ORIGINAL_CONSOLE;
5552
- var isProcessingConsole = false;
5553
- var isInternalLogging = false;
5554
- var ErrorTracking = class {
5555
- constructor(sendMessage) {
5556
- this.initialized = false;
5557
- this.fullyInitialized = false;
5558
- // 完全初始化完成标志
5559
- this.errorCache = /* @__PURE__ */ new Set();
5560
- this.errorHistory = [];
5561
- this.originalConsole = ORIGINAL_CONSOLE;
5562
- // 依赖注入
5563
- this.viewDetector = null;
5564
- this.interactionTracking = null;
5565
- this.sendMessage = sendMessage;
5566
- }
5567
- /**
5568
- * 内部日志方法,避免被控制台拦截器捕获
5569
- */
5570
- internalLog(level, ...args) {
5571
- isInternalLogging = true;
5572
- try {
5573
- ORIGINAL_CONSOLE[level](...args);
5574
- } finally {
5575
- isInternalLogging = false;
5576
- }
5577
- }
5578
- /** ----------------- 依赖注入方法 ----------------- */
5579
- /**
5580
- * 设置视图检测器
5581
- */
5582
- setViewDetector(viewDetector) {
5583
- this.viewDetector = viewDetector;
5584
- }
5585
- /**
5586
- * 设置交互追踪器
5587
- */
5588
- setInteractionTracking(interactionTracking) {
5589
- this.interactionTracking = interactionTracking;
5590
- }
5591
- /** ----------------- 初始化方法 ----------------- */
5592
- /**
5593
- * 初始化错误追踪
5594
- */
5595
- initialize() {
5596
- if (this.initialized) return;
5597
- this.setupGlobalErrorListeners();
5598
- this.setupConsoleInterception();
5599
- this.setupNetworkMonitoring();
5600
- this.initialized = true;
5601
- setTimeout(() => {
5602
- this.fullyInitialized = true;
5603
- }, 1e3);
5604
- }
5605
- /**
5606
- * 设置全局错误监听器
5607
- */
5608
- setupGlobalErrorListeners() {
5609
- window.addEventListener("error", (event) => {
5610
- event.preventDefault();
5611
- this.handleError(event.error || new Error(event.message), {
5612
- filename: event.filename,
5613
- lineno: event.lineno,
5614
- colno: event.colno,
5615
- type: "runtime",
5616
- source: "window.error"
5617
- });
5618
- });
5619
- window.addEventListener("unhandledrejection", (event) => {
5620
- event.preventDefault();
5621
- const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
5622
- this.handleError(error, {
5623
- type: "promise",
5624
- source: "unhandledrejection"
5625
- });
5626
- });
5627
- }
5628
- /**
5629
- * 设置控制台拦截
5630
- */
5631
- setupConsoleInterception() {
5632
- const consoleMethods = ["log", "warn", "error", "info", "debug"];
5633
- consoleMethods.forEach((method) => {
5634
- console[method] = (...args) => {
5635
- if (isProcessingConsole || isInternalLogging) {
5636
- ORIGINAL_CONSOLE[method]?.apply(console, args);
5637
- return;
5638
- }
5639
- isProcessingConsole = true;
5640
- try {
5641
- ORIGINAL_CONSOLE[method]?.apply(console, args);
5642
- this.safeForwardConsoleToParent(method, args);
5643
- } catch (error) {
5644
- this.internalLog("error", "[ErrorTracking] \u63A7\u5236\u53F0\u5904\u7406\u5931\u8D25:", error);
5645
- } finally {
5646
- isProcessingConsole = false;
5647
- }
5648
- };
5649
- });
5650
- }
5651
- /**
5652
- * 安全地将控制台输出转发到父窗口
5653
- */
5654
- safeForwardConsoleToParent(method, args) {
5655
- if (window.parent === window) return;
5656
- if (!this.fullyInitialized) return;
5657
- try {
5658
- let stack = null;
5659
- if (method === "warn" || method === "error") {
5660
- const error = new Error();
5661
- if (error.stack) {
5662
- stack = error.stack.split("\n").slice(2).join("\n");
5663
- }
5664
- }
5665
- const fullStack = new Error().stack;
5666
- const fileInfo = this.extractFileInfoFromStack(fullStack);
5667
- const serializedArgs = args.map((arg) => DeepSerializer.quickSerialize(arg));
5668
- const message = serializedArgs.map((arg) => typeof arg === "string" ? arg : JSON.stringify(arg, null, 2)).join(" ") + (stack ? "\n" + stack : "");
5669
- const lowerMessage = message.toLowerCase();
5670
- const isFromVite = (fileInfo.filename || "").toLowerCase().includes("vite") || lowerMessage.includes("@vite") || lowerMessage.includes("vite") || lowerMessage.includes("hmr");
5671
- const ignoreVitePatterns = [
5672
- /\[vite\]\s*hot updated/i,
5673
- /\[vite\]\s*connected/i,
5674
- /\[vite\]\s*connecting/i,
5675
- /\bhot updated\b/i,
5676
- /\bhmr\b.*\bupdated\b/i
5677
- ];
5678
- if (isFromVite && ignoreVitePatterns.some((re) => re.test(lowerMessage))) {
5679
- return;
5680
- }
5681
- const hasErrorKeywords = /\b(error|failed|overlay|compile|exception)\b/.test(lowerMessage);
5682
- const isViteHMRNonError = isFromVite && !hasErrorKeywords;
5683
- if (method === "error") {
5684
- const globalError = {
5685
- id: `console-error-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
5686
- message,
5687
- stack: stack || "",
5688
- source: "console",
5689
- location: {
5690
- filename: fileInfo.filename,
5691
- line: fileInfo.lineno,
5692
- column: fileInfo.colno
5693
- },
5694
- timestamp: Date.now(),
5695
- pageUrl: window.location.href,
5696
- pagePath: window.location.pathname + window.location.search + window.location.hash,
5697
- interactionTrail: [...window.__AUTO_ENGINEER_INTERACTION_TRAIL__ || []]
5698
- };
5699
- if (!isViteHMRNonError) {
5700
- window.__AUTO_ENGINEER_ERRORS__ = window.__AUTO_ENGINEER_ERRORS__ || [];
5701
- window.__AUTO_ENGINEER_ERRORS__.push(globalError);
5702
- this.manageArrayLength(window.__AUTO_ENGINEER_ERRORS__, ERROR_CONFIG.MAX_ERRORS);
5703
- }
5704
- }
5705
- const consoleLevelMap = {
5706
- log: "info",
5707
- warn: "warning",
5708
- error: "error",
5709
- info: "info",
5710
- debug: "debug"
5711
- };
5712
- this.sendMessage({
5713
- type: "CONSOLE_EVENT",
5714
- payload: {
5715
- type: consoleLevelMap[method] === "info" ? "info" : consoleLevelMap[method] === "warning" ? "warning" : consoleLevelMap[method] === "debug" ? "debug" : "error",
5716
- message,
5717
- logged_at: (/* @__PURE__ */ new Date()).toISOString(),
5718
- filename: fileInfo.filename,
5719
- lineno: fileInfo.lineno,
5720
- colno: fileInfo.colno,
5721
- raw: serializedArgs,
5722
- pageUrl: window.location.href,
5723
- pagePath: window.location.pathname + window.location.search + window.location.hash,
5724
- interactionTrail: this.getRecentInteractions()
5725
- },
5726
- timestamp: Date.now()
5727
- });
5728
- } catch (error) {
5729
- this.internalLog("error", "[ErrorTracking] \u63A7\u5236\u53F0\u8F6C\u53D1\u5931\u8D25:", error);
5730
- }
5731
- }
5732
- /**
5733
- * 设置网络监控
5734
- */
5735
- setupNetworkMonitoring() {
5736
- const self = this;
5737
- const originalFetch = window.fetch;
5738
- window.fetch = async (...args) => {
5739
- const startTime = Date.now();
5740
- try {
5741
- const response = await originalFetch(...args);
5742
- self.logNetworkRequest(args, response, Date.now() - startTime);
5743
- return response;
5744
- } catch (error) {
5745
- const duration = Date.now() - startTime;
5746
- const message = error && (error.message || String(error));
5747
- const match = typeof message === "string" ? message.match(/^HTTP\s+(\d+):\s*(.*)$/i) : null;
5748
- if (match) {
5749
- const status = Number(match[1]);
5750
- const statusText = match[2] || "";
5751
- const stack = new Error().stack;
5752
- const fileInfo = self.extractFileInfoFromStack(stack);
5753
- self.sendMessage({
5754
- type: "NETWORK_EVENT",
5755
- payload: {
5756
- type: "request_error",
5757
- url: args[0],
5758
- method: args[1]?.method || "GET",
5759
- status,
5760
- statusText,
5761
- filename: fileInfo.filename,
5762
- lineno: fileInfo.lineno,
5763
- colno: fileInfo.colno,
5764
- duration,
5765
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5766
- pageUrl: window.location.href,
5767
- interactionTrail: self.getRecentInteractions()
5768
- },
5769
- timestamp: Date.now()
5770
- });
5771
- } else {
5772
- self.logNetworkError(args, error, duration);
5773
- }
5774
- throw error;
5775
- }
5776
- };
5777
- }
5778
- /**
5779
- * 记录网络请求
5780
- */
5781
- logNetworkRequest(args, response, duration) {
5782
- const stack = new Error().stack;
5783
- const fileInfo = this.extractFileInfoFromStack(stack);
5784
- this.sendMessage({
5785
- type: "NETWORK_EVENT",
5786
- payload: {
5787
- type: response.status >= 200 && response.status < 300 ? "request_success" : "request_error",
5788
- url: args[0],
5789
- method: args[1]?.method || "GET",
5790
- status: response.status,
5791
- statusText: response.statusText,
5792
- filename: fileInfo.filename,
5793
- lineno: fileInfo.lineno,
5794
- colno: fileInfo.colno,
5795
- duration,
5796
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5797
- pageUrl: window.location.href,
5798
- interactionTrail: this.getRecentInteractions()
5799
- },
5800
- timestamp: Date.now()
5801
- });
5802
- }
5803
- /**
5804
- * 记录网络错误
5805
- */
5806
- logNetworkError(args, error, duration) {
5807
- const stack = new Error().stack;
5808
- const fileInfo = this.extractFileInfoFromStack(stack);
5809
- this.sendMessage({
5810
- type: "NETWORK_EVENT",
5811
- payload: {
5812
- type: "connection_error",
5813
- url: args[0],
5814
- method: args[1]?.method || "GET",
5815
- filename: fileInfo.filename,
5816
- lineno: fileInfo.lineno,
5817
- colno: fileInfo.colno,
5818
- duration,
5819
- // 网络请求耗时(毫秒)
5820
- error: {
5821
- message: error instanceof Error ? error.message : String(error),
5822
- stack: error instanceof Error ? error.stack : void 0
5823
- },
5824
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5825
- pageUrl: window.location.href,
5826
- interactionTrail: this.getRecentInteractions()
5827
- },
5828
- timestamp: Date.now()
5829
- });
5830
- }
5831
- /** ----------------- 错误处理核心方法 ----------------- */
5832
- /**
5833
- * 处理错误 - 统一使用控制台拦截格式
5834
- */
5835
- handleError(error, details = {}) {
5836
- if (!this.isDuplicateError(error, details)) {
5837
- this.sendUnifiedError(error, details);
5838
- }
5839
- }
5840
- /**
5841
- * 生成错误键用于去重
5842
- */
5843
- generateErrorKey(error, details) {
5844
- const message = error.message || "";
5845
- const filename = details.filename || "";
5846
- const lineno = details.lineno || 0;
5847
- const colno = details.colno || 0;
5848
- return `${message}|${filename}|${lineno}|${colno}`;
5849
- }
5850
- /**
5851
- * 检查是否为重复错误
5852
- */
5853
- isDuplicateError(error, details) {
5854
- const errorKey = this.generateErrorKey(error, details);
5855
- if (this.errorCache.has(errorKey)) {
5856
- return true;
5857
- }
5858
- this.errorCache.add(errorKey);
5859
- setTimeout(() => {
5860
- this.errorCache.delete(errorKey);
5861
- }, 2e3);
5862
- return false;
5863
- }
5864
- /**
5865
- * 发送统一格式的错误
5866
- */
5867
- sendUnifiedError(error, details = {}) {
5868
- if (window.parent === window) return;
5869
- if (!this.fullyInitialized) return;
5870
- try {
5871
- const currentViewInfo = this.viewDetector?.getCurrentViewInfo();
5872
- const payload = {
5873
- message: error.message,
5874
- stack: error.stack,
5875
- filename: details.filename,
5876
- lineno: details.lineno,
5877
- colno: details.colno,
5878
- timestamp: Date.now(),
5879
- type: details.type || "unknown",
5880
- severity: this.assessErrorSeverity(error.message, details.category),
5881
- category: details.category || this.categorizeError(error.message),
5882
- userAgent: navigator.userAgent,
5883
- url: window.location.href,
5884
- view: currentViewInfo?.title,
5885
- userInteractions: this.getRecentInteractions(),
5886
- // 页面信息
5887
- pagePath: window.location.pathname + window.location.search + window.location.hash,
5888
- // 错误存储
5889
- raw: window.__AUTO_ENGINEER_ERRORS__,
5890
- // 详细信息
5891
- details: {
5892
- ...DeepSerializer.quickSerialize(details),
5893
- serializedError: DeepSerializer.quickSerialize(error)
5894
- }
5895
- };
5896
- this.addToHistory(payload);
5897
- this.sendMessage({
5898
- type: "ERROR_EVENT",
5899
- payload,
5900
- timestamp: Date.now()
5901
- });
5902
- if (payload.severity === "critical" || payload.severity === "high") {
5903
- this.internalLog("error", "[ErrorTracking]:", payload);
5904
- }
5905
- } catch (sendError) {
5906
- this.internalLog("error", "[ErrorTracking]:", sendError);
5907
- }
5908
- }
5909
- /**
5910
- * 添加错误到历史记录
5911
- */
5912
- addToHistory(payload) {
5913
- this.errorHistory.push(payload);
5914
- this.manageArrayLength(this.errorHistory, ERROR_CONFIG.MAX_ERRORS);
5915
- const globalError = {
5916
- id: `error-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
5917
- message: payload.message,
5918
- stack: payload.stack || "",
5919
- source: payload.type,
5920
- location: {
5921
- filename: payload.filename || "",
5922
- line: payload.lineno || 0,
5923
- column: payload.colno || 0
5924
- },
5925
- timestamp: payload.timestamp,
5926
- pageUrl: window.location.href,
5927
- pagePath: window.location.pathname + window.location.search + window.location.hash,
5928
- interactionTrail: [...window.__AUTO_ENGINEER_INTERACTION_TRAIL__ || []]
5929
- };
5930
- window.__AUTO_ENGINEER_ERRORS__ = window.__AUTO_ENGINEER_ERRORS__ || [];
5931
- window.__AUTO_ENGINEER_ERRORS__.push(globalError);
5932
- this.manageArrayLength(window.__AUTO_ENGINEER_ERRORS__, ERROR_CONFIG.MAX_ERRORS);
5933
- }
5934
- /**
5935
- * 管理数组长度
5936
- */
5937
- manageArrayLength(array, maxLength) {
5938
- if (array.length > maxLength) {
5939
- array.shift();
5940
- }
5941
- }
5942
- /**
5943
- * 分类错误类型
5944
- */
5945
- categorizeError(message) {
5946
- const lowerMessage = message.toLowerCase();
5947
- if (ERROR_CONFIG.CATEGORY_KEYWORDS.SYNTAX.some((keyword) => lowerMessage.includes(keyword))) {
5948
- return "SYNTAX";
5949
- }
5950
- if (ERROR_CONFIG.CATEGORY_KEYWORDS.NETWORK.some((keyword) => lowerMessage.includes(keyword))) {
5951
- return "NETWORK";
5952
- }
5953
- if (ERROR_CONFIG.CATEGORY_KEYWORDS.RUNTIME.some((keyword) => lowerMessage.includes(keyword))) {
5954
- return "RUNTIME";
5955
- }
5956
- if (ERROR_CONFIG.CATEGORY_KEYWORDS.SECURITY.some((keyword) => lowerMessage.includes(keyword))) {
5957
- return "SECURITY";
5958
- }
5959
- if (ERROR_CONFIG.CATEGORY_KEYWORDS.PERFORMANCE.some((keyword) => lowerMessage.includes(keyword))) {
5960
- return "PERFORMANCE";
5961
- }
5962
- if (ERROR_CONFIG.CATEGORY_KEYWORDS.DEVELOPMENT.some((keyword) => lowerMessage.includes(keyword))) {
5963
- return "DEVELOPMENT";
5964
- }
5965
- return "UNKNOWN";
5966
- }
5967
- /**
5968
- * 评估错误严重性
5969
- */
5970
- assessErrorSeverity(message, category) {
5971
- const lowerMessage = message.toLowerCase();
5972
- if (ERROR_CONFIG.SEVERITY_KEYWORDS.CRITICAL.some((keyword) => lowerMessage.includes(keyword))) {
5973
- return "critical";
5974
- }
5975
- if (ERROR_CONFIG.SEVERITY_KEYWORDS.HIGH.some((keyword) => lowerMessage.includes(keyword))) {
5976
- return "high";
5977
- }
5978
- if (ERROR_CONFIG.SEVERITY_KEYWORDS.MEDIUM.some((keyword) => lowerMessage.includes(keyword))) {
5979
- return "medium";
5980
- }
5981
- if (ERROR_CONFIG.SEVERITY_KEYWORDS.LOW.some((keyword) => lowerMessage.includes(keyword))) {
5982
- return "low";
5983
- }
5984
- switch (category) {
5985
- case "SECURITY":
5986
- return "critical";
5987
- case "SYNTAX":
5988
- return "high";
5989
- case "RUNTIME":
5990
- return "high";
5991
- case "NETWORK":
5992
- return "medium";
5993
- case "DEVELOPMENT":
5994
- return "low";
5995
- default:
5996
- return "medium";
5997
- }
5998
- }
5999
- /**
6000
- * 获取最近的交互记录
6001
- */
6002
- getRecentInteractions() {
6003
- return this.interactionTracking?.getRecentInteractions() || [];
6004
- }
6005
- /** ----------------- 公共接口方法 ----------------- */
6006
- /**
6007
- * 获取错误统计
6008
- */
6009
- getErrorStats() {
6010
- return {
6011
- totalErrors: this.errorHistory.length,
6012
- jsErrors: this.errorHistory.filter((e) => e.severity === "high").length,
6013
- networkErrors: this.errorHistory.filter((e) => e.message.includes("network")).length,
6014
- consoleErrors: this.errorHistory.filter((e) => e.details?.source === "console").length,
6015
- lastErrorTime: this.errorHistory.length > 0 ? this.errorHistory[this.errorHistory.length - 1].timestamp : 0
6016
- };
6017
- }
6018
- /**
6019
- * 获取错误历史
6020
- */
6021
- getErrorHistory() {
6022
- return [...this.errorHistory];
6023
- }
6024
- /**
6025
- * 清除错误历史
6026
- */
6027
- clearErrorHistory() {
6028
- this.errorHistory = [];
6029
- this.errorCache.clear();
6030
- }
6031
- /**
6032
- * 从调用栈中提取文件信息(文件名、行号、列号)
6033
- */
6034
- extractFileInfoFromStack(stack) {
6035
- const defaultResult = { filename: "", lineno: 0, colno: 0 };
6036
- if (!stack) return defaultResult;
6037
- try {
6038
- const lines = stack.split("\n");
6039
- for (let i = 3; i < lines.length; i++) {
6040
- const line = lines[i];
6041
- const match = line.match(/(?:at\s+.*?\s+\()?([^()]+):(\d+):(\d+)\)?$/);
6042
- if (match) {
6043
- const fullPath = match[1];
6044
- const lineno = parseInt(match[2], 10) || 0;
6045
- const colno = parseInt(match[3], 10) || 0;
6046
- const filename = fullPath.split("/").pop() || fullPath.split("\\").pop() || fullPath;
6047
- if (!filename.includes("ErrorTracking") && !filename.includes("unified-error-handler") && filename !== "anonymous") {
6048
- return { filename, lineno, colno };
6049
- }
6050
- }
6051
- }
6052
- } catch (error) {
6053
- this.internalLog("warn", "[ErrorTracking] \u89E3\u6790\u8C03\u7528\u6808\u5931\u8D25:", error);
6054
- }
6055
- return defaultResult;
6056
- }
6057
- /**
6058
- * 从调用栈中提取文件名(保持向后兼容)
6059
- */
6060
- // private extractFilenameFromStack(stack?: string): string {
6061
- // return this.extractFileInfoFromStack(stack).filename;
6062
- // }
6063
- /**
6064
- * 手动启用控制台拦截
6065
- */
6066
- enableConsoleInterception() {
6067
- this.fullyInitialized = true;
6068
- }
6069
- /**
6070
- * 手动禁用控制台拦截
6071
- */
6072
- disableConsoleInterception() {
6073
- this.fullyInitialized = false;
6074
- }
6075
- /**
6076
- * 销毁错误追踪
6077
- */
6078
- destroy() {
6079
- Object.keys(this.originalConsole).forEach((method) => {
6080
- if (this.originalConsole[method]) {
6081
- console[method] = this.originalConsole[method];
6082
- }
6083
- });
6084
- this.initialized = false;
6085
- }
6086
- };
6087
-
6088
- // src/utils/unified-error-handler/utils/SelectorUtils.ts
6089
- function getElementClasses(element) {
6090
- const classAttr = element.getAttribute("class");
6091
- if (classAttr && classAttr.trim().length > 0) {
6092
- return dedupeAndClean(classAttr.split(/\s+/));
6093
- }
6094
- const anyEl = element;
6095
- if (typeof anyEl.className === "string") {
6096
- return dedupeAndClean(anyEl.className.split(/\s+/));
6097
- }
6098
- if (anyEl.className && typeof anyEl.className.baseVal === "string") {
6099
- return dedupeAndClean(anyEl.className.baseVal.split(/\s+/));
6100
- }
6101
- if (anyEl.classList && anyEl.classList.length > 0) {
6102
- return dedupeAndClean(Array.from(anyEl.classList));
6103
- }
6104
- return [];
6105
- }
6106
- function dedupeAndClean(arr) {
6107
- const cleaned = arr.map((s) => s.trim()).filter(Boolean);
6108
- return Array.from(new Set(cleaned));
6109
- }
6110
-
6111
- // src/utils/unified-error-handler/features/InteractionTracking.ts
6112
- var InteractionTracking = class {
6113
- constructor(sendMessage) {
6114
- this.interactions = [];
6115
- this.isTracking = false;
6116
- this.trackingConfig = {
6117
- maxInteractions: ERROR_CONFIG.MAX_INTERACTIONS,
6118
- trackClicks: true,
6119
- trackInputs: true,
6120
- trackScrolls: true,
6121
- trackKeyboard: true,
6122
- trackMouse: false,
6123
- // 默认关闭鼠标移动追踪,避免过多数据
6124
- trackFocus: true,
6125
- trackResize: true,
6126
- trackNavigation: true,
6127
- sensitiveInputFilter: true,
6128
- debounceTime: 100
6129
- };
6130
- // 防抖定时器
6131
- this.debounceTimers = /* @__PURE__ */ new Map();
6132
- this.eventListeners = [];
6133
- this.sendMessage = sendMessage;
6134
- }
6135
- /** ----------------- 主要控制方法 ----------------- */
6136
- /**
6137
- * 开始追踪
6138
- */
6139
- startTracking() {
6140
- if (this.isTracking) return;
6141
- this.setupEventListeners();
6142
- this.isTracking = true;
6143
- this.trackInteraction("navigation", void 0, {
6144
- type: "page_load",
6145
- url: window.location.href,
6146
- title: document.title,
6147
- timestamp: Date.now()
6148
- });
6149
- }
6150
- /**
6151
- * 停止追踪
6152
- */
6153
- stopTracking() {
6154
- if (!this.isTracking) return;
6155
- this.removeEventListeners();
6156
- this.isTracking = false;
6157
- }
6158
- /** ----------------- 事件监听器设置 ----------------- */
6159
- /**
6160
- * 设置事件监听器
6161
- */
6162
- setupEventListeners() {
6163
- if (this.trackingConfig.trackClicks) {
6164
- this.addEventListenerWithCleanup(document, "click", this.handleClick.bind(this), {
6165
- passive: true,
6166
- capture: true
6167
- });
6168
- }
6169
- if (this.trackingConfig.trackInputs) {
6170
- this.addEventListenerWithCleanup(document, "input", this.handleInput.bind(this), {
6171
- passive: true
6172
- });
6173
- this.addEventListenerWithCleanup(document, "change", this.handleChange.bind(this), {
6174
- passive: true
6175
- });
6176
- }
6177
- if (this.trackingConfig.trackScrolls) {
6178
- this.addEventListenerWithCleanup(document, "scroll", this.handleScroll.bind(this), {
6179
- passive: true
6180
- });
6181
- }
6182
- if (this.trackingConfig.trackKeyboard) {
6183
- this.addEventListenerWithCleanup(document, "keydown", this.handleKeyDown.bind(this), {
6184
- passive: true
6185
- });
6186
- this.addEventListenerWithCleanup(document, "keyup", this.handleKeyUp.bind(this), {
6187
- passive: true
6188
- });
6189
- }
6190
- if (this.trackingConfig.trackMouse) {
6191
- this.addEventListenerWithCleanup(document, "mousemove", this.handleMouseMove.bind(this), {
6192
- passive: true
6193
- });
6194
- }
6195
- if (this.trackingConfig.trackFocus) {
6196
- this.addEventListenerWithCleanup(document, "focus", this.handleFocus.bind(this), {
6197
- passive: true,
6198
- capture: true
6199
- });
6200
- this.addEventListenerWithCleanup(document, "blur", this.handleBlur.bind(this), {
6201
- passive: true,
6202
- capture: true
6203
- });
6204
- }
6205
- if (this.trackingConfig.trackResize) {
6206
- this.addEventListenerWithCleanup(window, "resize", this.handleResize.bind(this), {
6207
- passive: true
6208
- });
6209
- }
6210
- if (this.trackingConfig.trackNavigation) {
6211
- this.setupNavigationTracking();
6212
- }
6213
- this.addEventListenerWithCleanup(document, "submit", this.handleSubmit.bind(this), {
6214
- passive: true
6215
- });
6216
- this.addEventListenerWithCleanup(document, "visibilitychange", this.handleVisibilityChange.bind(this), {
6217
- passive: true
6218
- });
6219
- }
6220
- /**
6221
- * 添加事件监听器并记录以便清理
6222
- */
6223
- addEventListenerWithCleanup(element, event, handler, options) {
6224
- element.addEventListener(event, handler, options);
6225
- this.eventListeners.push({ element, event, handler, options });
6226
- }
6227
- /**
6228
- * 移除所有事件监听器
6229
- */
6230
- removeEventListeners() {
6231
- this.eventListeners.forEach(({ element, event, handler }) => {
6232
- element.removeEventListener(event, handler);
6233
- });
6234
- this.eventListeners = [];
6235
- this.debounceTimers.forEach((timer) => clearTimeout(timer));
6236
- this.debounceTimers.clear();
6237
- }
6238
- /**
6239
- * 设置导航追踪
6240
- */
6241
- setupNavigationTracking() {
6242
- this.addEventListenerWithCleanup(window, "popstate", this.handlePopState.bind(this), {
6243
- passive: true
6244
- });
6245
- const originalPushState = history.pushState;
6246
- const originalReplaceState = history.replaceState;
6247
- history.pushState = (...args) => {
6248
- this.trackInteraction("navigation", void 0, {
6249
- type: "pushState",
6250
- url: args[2] || window.location.href,
6251
- state: args[0]
6252
- });
6253
- return originalPushState.apply(history, args);
6254
- };
6255
- history.replaceState = (...args) => {
6256
- this.trackInteraction("navigation", void 0, {
6257
- type: "replaceState",
6258
- url: args[2] || window.location.href,
6259
- state: args[0]
6260
- });
6261
- return originalReplaceState.apply(history, args);
6262
- };
6263
- }
6264
- /** ----------------- 事件处理方法 ----------------- */
6265
- /**
6266
- * 处理点击事件
6267
- */
6268
- handleClick(event) {
6269
- if (!this.isTracking) return;
6270
- const target = event.target;
6271
- this.trackInteraction("click", target, {
6272
- x: event.clientX,
6273
- y: event.clientY,
6274
- button: event.button,
6275
- ctrlKey: event.ctrlKey,
6276
- shiftKey: event.shiftKey,
6277
- altKey: event.altKey,
6278
- metaKey: event.metaKey
6279
- });
6280
- }
6281
- /**
6282
- * 处理输入事件
6283
- */
6284
- handleInput(event) {
6285
- if (!this.isTracking) return;
6286
- const target = event.target;
6287
- if (this.isSensitiveInput(target)) return;
6288
- this.debounceTrack("input", () => {
6289
- this.trackInteraction("input", target, {
6290
- value: target.value?.substring(0, 50),
6291
- // 限制长度
6292
- inputType: target.type,
6293
- name: target.name
6294
- });
6295
- });
6296
- }
6297
- /**
6298
- * 处理变化事件
6299
- */
6300
- handleChange(event) {
6301
- if (!this.isTracking) return;
6302
- const target = event.target;
6303
- if (this.isSensitiveInput(target)) return;
6304
- this.trackInteraction("change", target, {
6305
- value: target.value?.substring(0, 50),
6306
- inputType: target.type,
6307
- name: target.name
6308
- });
6309
- }
6310
- /**
6311
- * 处理滚动事件
6312
- */
6313
- handleScroll() {
6314
- if (!this.isTracking) return;
6315
- this.debounceTrack("scroll", () => {
6316
- this.trackInteraction("scroll", void 0, {
6317
- scrollX: window.scrollX,
6318
- scrollY: window.scrollY,
6319
- scrollTop: document.documentElement.scrollTop
6320
- });
6321
- });
6322
- }
6323
- /**
6324
- * 处理键盘按下事件
6325
- */
6326
- handleKeyDown(event) {
6327
- if (!this.isTracking) return;
6328
- const keyboardEvent = event;
6329
- if (keyboardEvent.ctrlKey || keyboardEvent.metaKey || keyboardEvent.altKey || keyboardEvent.shiftKey || ["Enter", "Escape", "Tab", "Backspace", "Delete"].includes(keyboardEvent.key)) {
6330
- this.trackInteraction("keydown", keyboardEvent.target, {
6331
- key: keyboardEvent.key,
6332
- code: keyboardEvent.code,
6333
- ctrlKey: keyboardEvent.ctrlKey,
6334
- metaKey: keyboardEvent.metaKey,
6335
- altKey: keyboardEvent.altKey,
6336
- shiftKey: keyboardEvent.shiftKey
6337
- });
6338
- }
6339
- }
6340
- /**
6341
- * 处理键盘释放事件
6342
- */
6343
- handleKeyUp(event) {
6344
- if (!this.isTracking) return;
6345
- const keyboardEvent = event;
6346
- if (["Enter", "Escape", "Tab"].includes(keyboardEvent.key)) {
6347
- this.trackInteraction("keyup", keyboardEvent.target, {
6348
- key: keyboardEvent.key,
6349
- code: keyboardEvent.code
6350
- });
6351
- }
6352
- }
6353
- /**
6354
- * 处理鼠标移动事件
6355
- */
6356
- handleMouseMove(event) {
6357
- if (!this.isTracking) return;
6358
- this.debounceTrack("mousemove", () => {
6359
- this.trackInteraction("mousemove", void 0, {
6360
- x: event.clientX,
6361
- y: event.clientY
6362
- });
6363
- }, 200);
6364
- }
6365
- /**
6366
- * 处理焦点事件
6367
- */
6368
- handleFocus(event) {
6369
- if (!this.isTracking) return;
6370
- const target = event.target;
6371
- this.trackInteraction("focus", target, {
6372
- tagName: target.tagName.toLowerCase(),
6373
- type: target.type || "",
6374
- name: target.name || ""
6375
- });
6376
- }
6377
- /**
6378
- * 处理失焦事件
6379
- */
6380
- handleBlur(event) {
6381
- if (!this.isTracking) return;
6382
- const target = event.target;
6383
- this.trackInteraction("blur", target, {
6384
- tagName: target.tagName.toLowerCase()
6385
- });
6386
- }
6387
- /**
6388
- * 处理窗口大小变化
6389
- */
6390
- handleResize() {
6391
- if (!this.isTracking) return;
6392
- this.debounceTrack("resize", () => {
6393
- this.trackInteraction("resize", void 0, {
6394
- width: window.innerWidth,
6395
- height: window.innerHeight
6396
- });
6397
- });
6398
- }
6399
- /**
6400
- * 处理表单提交
6401
- */
6402
- handleSubmit(event) {
6403
- if (!this.isTracking) return;
6404
- const target = event.target;
6405
- this.trackInteraction("submit", target, {
6406
- action: target.action,
6407
- method: target.method,
6408
- fieldCount: target.elements.length
6409
- });
6410
- }
6411
- /**
6412
- * 处理页面可见性变化
6413
- */
6414
- handleVisibilityChange() {
6415
- if (!this.isTracking) return;
6416
- this.trackInteraction("visibility", void 0, {
6417
- hidden: document.hidden,
6418
- visibilityState: document.visibilityState
6419
- });
6420
- }
6421
- /**
6422
- * 处理 popstate 事件
6423
- */
6424
- handlePopState() {
6425
- if (!this.isTracking) return;
6426
- this.trackInteraction("navigation", void 0, {
6427
- type: "popstate",
6428
- url: window.location.href
6429
- });
6430
- }
6431
- /** ----------------- 辅助方法 ----------------- */
6432
- /**
6433
- * 防抖追踪
6434
- */
6435
- debounceTrack(key, callback, delay) {
6436
- const debounceTime = delay || this.trackingConfig.debounceTime;
6437
- if (this.debounceTimers.has(key)) {
6438
- clearTimeout(this.debounceTimers.get(key));
6439
- }
6440
- const timer = setTimeout(callback, debounceTime);
6441
- this.debounceTimers.set(key, timer);
6442
- }
6443
- /**
6444
- * 追踪交互
6445
- */
6446
- trackInteraction(type, element, details) {
6447
- const interaction = {
6448
- type,
6449
- element: element ? this.getElementSelector(element) : void 0,
6450
- timestamp: Date.now(),
6451
- details
6452
- };
6453
- this.interactions.push(interaction);
6454
- this.manageArrayLength(this.interactions, this.trackingConfig.maxInteractions);
6455
- const globalInteraction = {
6456
- ...interaction,
6457
- pageUrl: window.location.href,
6458
- pagePath: window.location.pathname + window.location.search + window.location.hash
6459
- };
6460
- window.__AUTO_ENGINEER_INTERACTION_TRAIL__ = window.__AUTO_ENGINEER_INTERACTION_TRAIL__ || [];
6461
- window.__AUTO_ENGINEER_INTERACTION_TRAIL__.push(globalInteraction);
6462
- this.manageArrayLength(window.__AUTO_ENGINEER_INTERACTION_TRAIL__, 8);
6463
- }
6464
- /**
6465
- * 获取元素选择器
6466
- */
6467
- getElementSelector(element) {
6468
- if (element.id) return `#${element.id}`;
6469
- const classes = getElementClasses(element);
6470
- if (classes.length > 0) {
6471
- return `.${classes[0]}`;
6472
- }
6473
- const dataTestId = element.getAttribute("data-testid");
6474
- if (dataTestId) return `[data-testid="${dataTestId}"]`;
6475
- const dataId = element.getAttribute("data-id");
6476
- if (dataId) return `[data-id="${dataId}"]`;
6477
- return element.tagName.toLowerCase();
6478
- }
6479
- /**
6480
- * 检查是否为敏感输入
6481
- */
6482
- isSensitiveInput(element) {
6483
- if (!this.trackingConfig.sensitiveInputFilter) return false;
6484
- const sensitiveTypes = ["password", "email", "tel", "ssn", "credit-card"];
6485
- const sensitiveNames = ["password", "email", "phone", "ssn", "credit", "card", "cvv", "pin"];
6486
- return sensitiveTypes.includes(element.type) || sensitiveNames.some(
6487
- (name) => element.name?.toLowerCase().includes(name) || element.placeholder?.toLowerCase().includes(name) || element.id?.toLowerCase().includes(name)
6488
- );
6489
- }
6490
- /**
6491
- * 管理数组长度
6492
- */
6493
- manageArrayLength(array, maxLength) {
6494
- if (array.length > maxLength) {
6495
- array.shift();
6496
- }
6497
- }
6498
- /** ----------------- 公共接口方法 ----------------- */
6499
- /**
6500
- * 获取交互历史
6501
- */
6502
- getInteractionHistory() {
6503
- return [...this.interactions];
6504
- }
6505
- /**
6506
- * 获取最近的交互记录
6507
- */
6508
- getRecentInteractions(count = 8) {
6509
- return this.interactions.slice(-count);
6510
- }
6511
- /**
6512
- * 手动发送交互数据到父窗口(用于测试或特殊情况)
6513
- */
6514
- sendInteractionData() {
6515
- if (this.interactions.length === 0) return;
6516
- this.sendMessage({
6517
- type: "INTERACTION_EVENT",
6518
- payload: {
6519
- type: "summary",
6520
- interactions: this.interactions,
6521
- count: this.interactions.length,
6522
- timeRange: {
6523
- start: this.interactions[0]?.timestamp || Date.now(),
6524
- end: this.interactions[this.interactions.length - 1]?.timestamp || Date.now()
6525
- },
6526
- summary: this.generateInteractionSummary()
6527
- },
6528
- timestamp: Date.now()
6529
- });
6530
- }
6531
- /**
6532
- * 生成交互摘要
6533
- */
6534
- generateInteractionSummary() {
6535
- const summary = {
6536
- totalInteractions: this.interactions.length,
6537
- typeCount: {},
6538
- uniqueElements: /* @__PURE__ */ new Set(),
6539
- timeSpan: 0
6540
- };
6541
- this.interactions.forEach((interaction) => {
6542
- summary.typeCount[interaction.type] = (summary.typeCount[interaction.type] || 0) + 1;
6543
- if (interaction.element) {
6544
- summary.uniqueElements.add(interaction.element);
6545
- }
6546
- });
6547
- if (this.interactions.length > 1) {
6548
- summary.timeSpan = this.interactions[this.interactions.length - 1].timestamp - this.interactions[0].timestamp;
6549
- }
6550
- return {
6551
- ...summary,
6552
- uniqueElements: Array.from(summary.uniqueElements),
6553
- mostCommonType: Object.entries(summary.typeCount).sort(([, a], [, b]) => b - a)[0]?.[0] || "unknown"
6554
- };
6555
- }
6556
- /**
6557
- * 清除交互历史
6558
- */
6559
- clearInteractionHistory() {
6560
- this.interactions = [];
6561
- }
6562
- /**
6563
- * 更新追踪配置
6564
- */
6565
- updateConfig(newConfig) {
6566
- this.trackingConfig = { ...this.trackingConfig, ...newConfig };
6567
- if (this.isTracking) {
6568
- this.removeEventListeners();
6569
- this.setupEventListeners();
6570
- }
6571
- }
6572
- /**
6573
- * 获取追踪状态
6574
- */
6575
- isTrackingActive() {
6576
- return this.isTracking;
6577
- }
6578
- /**
6579
- * 销毁交互追踪
6580
- */
6581
- destroy() {
6582
- this.stopTracking();
6583
- this.interactions = [];
6584
- }
6585
- };
6586
-
6587
- // src/utils/unified-error-handler/features/MessageBridge.ts
6588
- var getOriginalConsole2 = () => window.__originalConsole || {
6589
- log: console.log.bind(console),
6590
- warn: console.warn.bind(console),
6591
- error: console.error.bind(console),
6592
- info: console.info.bind(console),
6593
- debug: console.debug.bind(console)
6594
- };
6595
- var MessageBridge = class {
6596
- constructor(sendMessage) {
6597
- this.componentTreeGenerator = null;
6598
- this.messageSender = createDefaultMessageSender({
6599
- addTimestamp: true,
6600
- enableDebugLog: false
6601
- });
6602
- this.sendMessage = sendMessage || this.messageSender.createSendFunction();
6603
- this.setupMessageListener();
6604
- }
6605
- /** ----------------- 依赖注入方法 ----------------- */
6606
- /**
6607
- * 设置组件树生成器
6608
- */
6609
- setComponentTreeGenerator(componentTreeGenerator) {
6610
- this.componentTreeGenerator = componentTreeGenerator;
6611
- }
6612
- /** ----------------- 消息监听设置 ----------------- */
6613
- /**
6614
- * 设置消息监听器
6615
- */
6616
- setupMessageListener() {
6617
- this.messageListener = (event) => {
6618
- if (!this.isOriginAllowed(event.origin)) {
6619
- return;
6620
- }
6621
- if (event.data && typeof event.data === "object" && event.data.type) {
6622
- this.handleMessage(event.data);
6623
- }
6624
- };
6625
- window.addEventListener("message", this.messageListener);
6626
- }
6627
- /**
6628
- * 检查来源是否被允许
6629
- */
6630
- isOriginAllowed(origin) {
6631
- return GLOBAL_CONFIG.ALLOWED_ORIGINS.some(
6632
- (allowedOrigin) => origin.includes(allowedOrigin.replace("https://", "").replace("http://", ""))
6633
- );
6634
- }
6635
- /** ----------------- 主要消息处理方法 ----------------- */
6636
- /**
6637
- * 处理消息
6638
- */
6639
- handleMessage(message) {
6640
- try {
6641
- const { type, payload } = message;
6642
- switch (type) {
6643
- case "SET_ELEMENT_CONTENT":
6644
- this.handleSetElementContent(payload);
6645
- break;
6646
- case "SET_ELEMENT_ATTRS":
6647
- this.handleSetElementAttrs(payload);
6648
- break;
6649
- case "DUPLICATE_ELEMENT_REQUESTED":
6650
- this.handleDuplicateElementRequested(payload);
6651
- break;
6652
- case "EDIT_TEXT_REQUESTED":
6653
- this.handleEditTextRequested(payload);
6654
- break;
6655
- // 组件树相关消息
6656
- case "REQUEST_COMPONENT_TREE":
6657
- this.handleRequestComponentTree();
6658
- break;
6659
- case "GET_PARENT_ELEMENT":
6660
- this.handleGetParentElement(payload);
6661
- break;
6662
- // 样式相关消息
6663
- case "SET_STYLESHEET":
6664
- this.handleSetStylesheet(payload);
6665
- break;
6666
- default:
6667
- break;
6668
- }
6669
- } catch (error) {
6670
- console.error("[MessageBridge] \u5904\u7406\u6D88\u606F\u5931\u8D25:", error);
6671
- this.sendMessage({
6672
- type: "ERROR_EVENT",
6673
- payload: {
6674
- type: "message_handling",
6675
- originalMessage: message,
6676
- error: error instanceof Error ? error.message : String(error)
6677
- },
6678
- timestamp: Date.now()
6679
- });
6680
- }
6681
- }
6682
- /** ----------------- 元素操作消息处理 ----------------- */
6683
- /**
6684
- * 处理设置元素内容
6685
- */
6686
- handleSetElementContent(payload) {
6687
- if (!payload?.selector || !payload?.content) return;
6688
- const elements = document.querySelectorAll(payload.selector);
6689
- elements.forEach((element) => {
6690
- if (element instanceof HTMLElement) {
6691
- element.innerHTML = payload.content;
6692
- }
6693
- });
6694
- this.sendMessage({
6695
- type: "ELEMENT_EVENT",
6696
- payload: {
6697
- type: "content_updated",
6698
- selector: payload.selector,
6699
- content: payload.content,
6700
- elementsUpdated: elements.length
6701
- },
6702
- timestamp: Date.now()
6703
- });
6704
- }
6705
- /**
6706
- * 处理设置元素属性
6707
- */
6708
- handleSetElementAttrs(payload) {
6709
- if (!payload?.selector || !payload?.attrs) return;
6710
- const elements = document.querySelectorAll(payload.selector);
6711
- elements.forEach((element) => {
6712
- Object.entries(payload.attrs).forEach(([key, value]) => {
6713
- element.setAttribute(key, String(value));
6714
- });
6715
- });
6716
- this.sendMessage({
6717
- type: "ELEMENT_EVENT",
6718
- payload: {
6719
- type: "attrs_updated",
6720
- selector: payload.selector,
6721
- attrs: payload.attrs,
6722
- elementsUpdated: elements.length
6723
- },
6724
- timestamp: Date.now()
6725
- });
6726
- }
6727
- /**
6728
- * 处理复制元素请求
6729
- */
6730
- handleDuplicateElementRequested(payload) {
6731
- if (!payload?.selector) return;
6732
- const element = document.querySelector(payload.selector);
6733
- if (element && element.parentElement) {
6734
- const clone = element.cloneNode(true);
6735
- clone.setAttribute("data-duplicated", "true");
6736
- element.parentElement.appendChild(clone);
6737
- this.sendMessage({
6738
- type: "ELEMENT_EVENT",
6739
- payload: {
6740
- type: "duplicated",
6741
- originalSelector: payload.selector,
6742
- duplicatedElement: this.getElementInfo(clone)
6743
- },
6744
- timestamp: Date.now()
6745
- });
6746
- }
6747
- }
6748
- /**
6749
- * 处理编辑文本请求
6750
- */
6751
- handleEditTextRequested(payload) {
6752
- if (!payload?.selector) return;
6753
- const element = document.querySelector(payload.selector);
6754
- if (element instanceof HTMLElement) {
6755
- element.setAttribute("contenteditable", "true");
6756
- element.focus();
6757
- const handleInput = () => {
6758
- this.sendMessage({
6759
- type: "ELEMENT_EVENT",
6760
- payload: {
6761
- type: "text_updated",
6762
- selector: payload.selector,
6763
- content: element.innerText
6764
- },
6765
- timestamp: Date.now()
6766
- });
6767
- };
6768
- const handleBlur = () => {
6769
- element.removeAttribute("contenteditable");
6770
- element.removeEventListener("input", handleInput);
6771
- element.removeEventListener("blur", handleBlur);
6772
- this.sendMessage({
6773
- type: "ELEMENT_EVENT",
6774
- payload: {
6775
- type: "edit_completed",
6776
- selector: payload.selector,
6777
- finalContent: element.innerText
6778
- },
6779
- timestamp: Date.now()
6780
- });
6781
- };
6782
- element.addEventListener("input", handleInput);
6783
- element.addEventListener("blur", handleBlur);
6784
- }
6785
- }
6786
- /** ----------------- 组件树相关消息处理 ----------------- */
6787
- /**
6788
- * 处理请求组件树
6789
- */
6790
- handleRequestComponentTree() {
6791
- if (!this.componentTreeGenerator) return;
6792
- try {
6793
- const rootElement = document.querySelector("#root") || document.body;
6794
- const componentTree = this.componentTreeGenerator.generateComponentTree(rootElement);
6795
- this.sendMessage({
6796
- type: "COMPONENT_EVENT",
6797
- payload: {
6798
- type: "tree_response",
6799
- ...componentTree
6800
- },
6801
- timestamp: Date.now()
6802
- });
6803
- } catch (error) {
6804
- const originalConsole = getOriginalConsole2();
6805
- originalConsole.error("[MessageBridge] \u751F\u6210\u7EC4\u4EF6\u6811\u5931\u8D25:", error);
6806
- this.sendMessage({
6807
- type: "COMPONENT_EVENT",
6808
- payload: {
6809
- type: "tree_error",
6810
- error: error instanceof Error ? error.message : String(error)
6811
- },
6812
- timestamp: Date.now()
6813
- });
6814
- }
6815
- }
6816
- /**
6817
- * 处理获取父元素
6818
- */
6819
- handleGetParentElement(payload) {
6820
- if (!payload?.selector) return;
6821
- const element = document.querySelector(payload.selector);
6822
- if (element && element.parentElement) {
6823
- const parentInfo = this.getElementInfo(element.parentElement);
6824
- this.sendMessage({
6825
- type: "ELEMENT_EVENT",
6826
- payload: {
6827
- type: "parent_element_response",
6828
- childSelector: payload.selector,
6829
- parentElement: parentInfo
6830
- },
6831
- timestamp: Date.now()
6832
- });
6833
- } else {
6834
- this.sendMessage({
6835
- type: "ELEMENT_EVENT",
6836
- payload: {
6837
- type: "parent_element_response",
6838
- childSelector: payload.selector,
6839
- parentElement: null
6840
- },
6841
- timestamp: Date.now()
6842
- });
6843
- }
6844
- }
6845
- /** ----------------- 样式相关消息处理 ----------------- */
6846
- /**
6847
- * 处理设置样式表
6848
- */
6849
- handleSetStylesheet(payload) {
6850
- if (!payload?.stylesheet) return;
6851
- const styleId = "dynamic-stylesheet";
6852
- let styleElement = document.getElementById(styleId);
6853
- if (styleElement) {
6854
- styleElement.textContent = payload.stylesheet;
6855
- } else {
6856
- styleElement = document.createElement("style");
6857
- styleElement.id = styleId;
6858
- styleElement.textContent = payload.stylesheet;
6859
- document.head.appendChild(styleElement);
6860
- }
6861
- this.sendMessage({
6862
- type: "STYLE_EVENT",
6863
- payload: {
6864
- type: "stylesheet_updated",
6865
- styleId,
6866
- stylesheetLength: payload.stylesheet.length
6867
- },
6868
- timestamp: Date.now()
6869
- });
6870
- }
6871
- /** ----------------- 辅助方法 ----------------- */
6872
- /**
6873
- * 获取元素信息
6874
- */
6875
- getElementInfo(element) {
6876
- return {
6877
- tagName: element.tagName.toLowerCase(),
6878
- id: element.id || void 0,
6879
- className: element.className || void 0,
6880
- textContent: element.textContent?.trim().substring(0, 100) || void 0,
6881
- attributes: this.getElementAttributes(element),
6882
- selector: this.getElementSelector(element),
6883
- boundingRect: element.getBoundingClientRect()
6884
- };
6885
- }
6886
- /**
6887
- * 获取元素属性
6888
- */
6889
- getElementAttributes(element) {
6890
- const attrs = {};
6891
- const importantAttrs = ["id", "class", "data-testid", "data-howone-id", "data-component-path", "href", "src", "type", "name"];
6892
- importantAttrs.forEach((attr) => {
6893
- const value = element.getAttribute(attr);
6894
- if (value) {
6895
- attrs[attr] = value;
6896
- }
6897
- });
6898
- return attrs;
6899
- }
6900
- /**
6901
- * 获取元素选择器
6902
- */
6903
- getElementSelector(element) {
6904
- if (element.id) return `#${element.id}`;
6905
- const dataTestId = element.getAttribute("data-testid");
6906
- if (dataTestId) return `[data-testid="${dataTestId}"]`;
6907
- const dataHowoneId = element.getAttribute("data-howone-id");
6908
- if (dataHowoneId) return `[data-howone-id="${dataHowoneId}"]`;
6909
- const classes = getElementClasses(element);
6910
- if (classes.length > 0) {
6911
- return `.${classes[0]}`;
6912
- }
6913
- return element.tagName.toLowerCase();
6914
- }
6915
- /** ----------------- 公共接口方法 ----------------- */
6916
- /**
6917
- * 发送消息到父窗口
6918
- */
6919
- sendToParent(type, payload) {
6920
- this.sendMessage({
6921
- type,
6922
- payload,
6923
- timestamp: Date.now()
6924
- });
6925
- }
6926
- /**
6927
- * 广播状态更新
6928
- */
6929
- broadcastStateUpdate(state) {
6930
- this.sendMessage({
6931
- type: "STATE_EVENT",
6932
- payload: {
6933
- type: "update",
6934
- ...state
6935
- },
6936
- timestamp: Date.now()
6937
- });
6938
- }
6939
- /** ----------------- 统一消息发送管理方法 ----------------- */
6940
- /**
6941
- * 获取统一的消息发送器实例
6942
- */
6943
- getMessageSender() {
6944
- return this.messageSender;
6945
- }
6946
- /**
6947
- * 创建新的发送函数(用于注入到其他模块)
6948
- */
6949
- createSendFunction() {
6950
- return this.messageSender.createSendFunction();
6951
- }
6952
- /**
6953
- * 更新消息发送器配置
6954
- */
6955
- updateMessageSenderOptions(options) {
6956
- this.messageSender.updateOptions(options);
6957
- }
6958
- /**
6959
- * 直接发送消息(使用统一的消息发送器)
6960
- */
6961
- sendUnifiedMessage(message) {
6962
- return this.messageSender.send(message);
6963
- }
6964
- /**
6965
- * 销毁消息桥接器
6966
- */
6967
- destroy() {
6968
- if (this.messageListener) {
6969
- window.removeEventListener("message", this.messageListener);
6970
- this.messageListener = void 0;
6971
- }
6972
- }
6973
- };
6974
-
6975
- // src/utils/unified-error-handler/core/ErrorHandler.ts
6976
- var getOriginalConsole3 = () => window.__originalConsole || {
6977
- log: console.log.bind(console),
6978
- warn: console.warn.bind(console),
6979
- error: console.error.bind(console),
6980
- info: console.info.bind(console),
6981
- debug: console.debug.bind(console)
6982
- };
6983
- var ErrorHandler = class {
6984
- constructor(options = {}) {
6985
- // 核心状态
6986
- this.initialized = false;
6987
- this.errorHistory = [];
6988
- // 工具模块
6989
- this.viteHMRDetector = null;
6990
- // 配置
6991
- this.config = {
6992
- maxErrorHistory: ERROR_CONFIG.MAX_ERRORS,
6993
- maxInteractionHistory: ERROR_CONFIG.MAX_INTERACTIONS,
6994
- enableViteHMR: true,
6995
- enableElementSelector: true,
6996
- enableInteractionTracking: true
6997
- };
6998
- this.config = { ...this.config, ...options };
6999
- this.messageSender = createDefaultMessageSender({
7000
- addTimestamp: true,
7001
- enableDebugLog: false
7002
- });
7003
- const sendMessage = this.messageSender.createSendFunction();
7004
- console.log("[ErrorHandler] \u521D\u59CB\u5316\u529F\u80FD\u6A21\u5757");
7005
- this.errorTracking = new ErrorTracking(sendMessage);
7006
- this.interactionTracking = new InteractionTracking(sendMessage);
7007
- this.messageBridge = new MessageBridge();
7008
- this.viewDetector = new ViewDetector();
7009
- this.hardRefreshManager = new HardRefreshManager(GLOBAL_CONFIG.ALLOWED_ORIGINS);
7010
- this.componentTreeGenerator = new ComponentTreeGenerator();
7011
- if (this.config.enableViteHMR && ViteHMRDetector.isViteEnvironment()) {
7012
- console.log("[ErrorHandler] Vite \u73AF\u5883\u68C0\u6D4B\u6210\u529F\uFF0C\u521D\u59CB\u5316\u68C0\u6D4B\u5668");
7013
- this.viteHMRDetector = new ViteHMRDetector(sendMessage);
7014
- }
7015
- }
7016
- /** ----------------- 主要初始化方法 ----------------- */
7017
- /**
7018
- * 初始化错误处理器
7019
- */
7020
- init() {
7021
- if (this.initialized) {
7022
- console.warn("[ErrorHandler] \u5DF2\u7ECF\u521D\u59CB\u5316\uFF0C\u8DF3\u8FC7\u91CD\u590D\u521D\u59CB\u5316");
7023
- return;
7024
- }
7025
- try {
7026
- this.initializeCore();
7027
- console.log("[ErrorHandler] \u6838\u5FC3\u529F\u80FD\u521D\u59CB\u5316\u5B8C\u6210");
7028
- this.setupModuleIntegration();
7029
- this.enableFeatures();
7030
- this.initialized = true;
7031
- } catch (error) {
7032
- console.error("[ErrorHandler] \u521D\u59CB\u5316\u5931\u8D25:", error);
7033
- throw error;
7034
- }
7035
- }
7036
- /**
7037
- * 初始化核心功能
7038
- */
7039
- initializeCore() {
7040
- this.initializeGlobalState();
7041
- this.setupDebugEndpoint();
7042
- this.errorTracking.initialize();
7043
- }
7044
- /**
7045
- * 初始化全局状态
7046
- */
7047
- initializeGlobalState() {
7048
- if (!window.__AUTO_ENGINEER_ERRORS__) {
7049
- window.__AUTO_ENGINEER_ERRORS__ = [];
7050
- }
7051
- if (!window.__AUTO_ENGINEER_INTERACTION_TRAIL__) {
7052
- window.__AUTO_ENGINEER_INTERACTION_TRAIL__ = [];
7053
- }
7054
- }
7055
- /**
7056
- * 设置调试端点
7057
- */
7058
- setupDebugEndpoint() {
7059
- if (window.location.pathname === "/__debug/errors") {
7060
- const errorData = {
7061
- errors: window.__AUTO_ENGINEER_ERRORS__ || [],
7062
- interactions: window.__AUTO_ENGINEER_INTERACTION_TRAIL__ || [],
7063
- timestamp: Date.now()
7064
- };
7065
- document.body.innerHTML = `<pre>${JSON.stringify(errorData, null, 2)}</pre>`;
7066
- return;
7067
- }
7068
- }
7069
- /**
7070
- * 设置模块间的协作
7071
- */
7072
- setupModuleIntegration() {
7073
- this.messageBridge.setComponentTreeGenerator(this.componentTreeGenerator);
7074
- this.errorTracking.setViewDetector(this.viewDetector);
7075
- this.errorTracking.setInteractionTracking(this.interactionTracking);
7076
- }
7077
- /**
7078
- * 启用功能模块
7079
- */
7080
- enableFeatures() {
7081
- if (this.config.enableInteractionTracking) {
7082
- this.interactionTracking.startTracking();
7083
- }
7084
- if (this.viteHMRDetector) {
7085
- this.viteHMRDetector.initialize();
7086
- }
7087
- this.handleHardRefreshLogic();
7088
- this.setupViewDetection();
7089
- }
7090
- /**
7091
- * 处理硬刷新逻辑
7092
- */
7093
- handleHardRefreshLogic() {
7094
- HardRefreshManager.cleanupRefreshParams();
7095
- const refreshStats = HardRefreshManager.getRefreshStats();
7096
- if (refreshStats.isHardRefresh) {
7097
- this.messageSender.send({
7098
- type: "SYSTEM_EVENT",
7099
- payload: {
7100
- type: "hard_refresh",
7101
- ...refreshStats
7102
- },
7103
- timestamp: Date.now()
7104
- });
7105
- }
7106
- }
7107
- /**
7108
- * 设置视图检测
7109
- */
7110
- setupViewDetection() {
7111
- const initialView = this.viewDetector.getCurrentViewInfo();
7112
- let lastViewTitle = initialView.title;
7113
- const checkViewChange = () => {
7114
- const currentView = this.viewDetector.getCurrentViewInfo();
7115
- if (currentView.title !== lastViewTitle) {
7116
- lastViewTitle = currentView.title;
7117
- }
7118
- };
7119
- setInterval(checkViewChange, 1e3);
7120
- }
7121
- /**
7122
- * 发送初始化完成消息
7123
- */
7124
- // private sendInitializationComplete(): void {
7125
- // this.messageSender.send({
7126
- // type: 'ERROR_EVENT',
7127
- // payload: {
7128
- // type: 'initialization',
7129
- // version: '2.0.0',
7130
- // features: {
7131
- // errorTracking: true,
7132
- // interactionTracking: this.config.enableInteractionTracking,
7133
- // elementSelector: this.config.enableElementSelector,
7134
- // viteHMR: !!this.viteHMRDetector,
7135
- // hardRefresh: true,
7136
- // viewDetection: true
7137
- // }
7138
- // },
7139
- // timestamp: Date.now()
7140
- // });
7141
- // }
7142
- /** ----------------- 公共接口方法 ----------------- */
7143
- /**
7144
- * 获取错误统计
7145
- */
7146
- getErrorStats() {
7147
- return this.errorTracking.getErrorStats();
7148
- }
7149
- /**
7150
- * 获取交互历史
7151
- */
7152
- getInteractionHistory() {
7153
- return this.interactionTracking.getInteractionHistory();
7154
- }
7155
- /**
7156
- * 获取当前视图信息
7157
- */
7158
- getCurrentView() {
7159
- return this.viewDetector.getCurrentViewInfo();
7160
- }
7161
- /**
7162
- * 执行硬刷新
7163
- */
7164
- async performHardRefresh(options) {
7165
- return await this.hardRefreshManager.performHardRefresh(options);
7166
- }
7167
- /**
7168
- * 获取深度序列化的错误历史
7169
- */
7170
- getSerializedErrorHistory() {
7171
- return DeepSerializer.serialize(this.errorHistory, {
7172
- maxDepth: 3,
7173
- maxArrayLength: 50
7174
- });
7175
- }
7176
- /**
7177
- * 检查是否在 Vite 环境中
7178
- */
7179
- isViteEnvironment() {
7180
- return ViteHMRDetector.isViteEnvironment();
7181
- }
7182
- /**
7183
- * 更新配置
7184
- */
7185
- updateConfig(newConfig) {
7186
- this.config = { ...this.config, ...newConfig };
7187
- }
7188
- /**
7189
- * 销毁错误处理器
7190
- */
7191
- destroy() {
7192
- try {
7193
- this.errorTracking.destroy();
7194
- this.interactionTracking.destroy();
7195
- this.messageBridge.destroy();
7196
- if (this.viteHMRDetector) {
7197
- this.viteHMRDetector.destroy();
7198
- this.viteHMRDetector = null;
7199
- }
7200
- if (this.viewDetector) {
7201
- this.viewDetector.clearCache();
7202
- }
7203
- this.initialized = false;
7204
- } catch (error) {
7205
- const originalConsole = getOriginalConsole3();
7206
- originalConsole.error("[ErrorHandler] \u9500\u6BC1\u65F6\u53D1\u751F\u9519\u8BEF:", error);
7207
- }
7208
- }
7209
- /**
7210
- * 检查是否已初始化
7211
- */
7212
- isInitialized() {
7213
- return this.initialized;
7214
- }
7215
- /**
7216
- * 报告当前状态
7217
- */
7218
- reportStatus() {
7219
- try {
7220
- const status = {
7221
- initialized: this.initialized,
7222
- errorStats: this.getErrorStats(),
7223
- currentView: this.getCurrentView(),
7224
- interactionHistory: this.getInteractionHistory(),
7225
- isViteEnvironment: this.isViteEnvironment(),
7226
- timestamp: Date.now()
7227
- };
7228
- this.messageSender.send({
7229
- type: "SYSTEM_EVENT",
7230
- payload: {
7231
- type: "status_report",
7232
- ...status
7233
- },
7234
- timestamp: Date.now()
7235
- });
7236
- } catch (error) {
7237
- const originalConsole = getOriginalConsole3();
7238
- originalConsole.error("[ErrorHandler] \u53D1\u9001\u72B6\u6001\u62A5\u544A\u65F6\u53D1\u751F\u9519\u8BEF:", error);
7239
- }
7240
- }
7241
- };
7242
-
7243
- // src/utils/unified-error-handler/simple.ts
7244
- var SimpleErrorHandler = class {
7245
- constructor() {
7246
- this.initialized = false;
7247
- }
7248
- // 使用明确赋值断言,因为在 init() 方法中会初始化
7249
- /**
7250
- * 初始化错误处理器
7251
- */
7252
- init() {
7253
- if (this.initialized) return;
7254
- this.sendMessage = createSimpleSendFunction({
7255
- addTimestamp: false,
7256
- // 简化版自己处理时间戳
7257
- enableDebugLog: false
7258
- });
7259
- this.setupErrorListeners();
7260
- this.setupCompatibility();
7261
- this.initialized = true;
7262
- }
7263
- /**
7264
- * 设置错误监听器
7265
- */
7266
- setupErrorListeners() {
7267
- window.addEventListener("error", (event) => {
7268
- this.sendError(event.error || new Error(event.message), {
7269
- filename: event.filename,
7270
- lineno: event.lineno,
7271
- colno: event.colno,
7272
- type: "runtime"
7273
- });
7274
- });
7275
- window.addEventListener("unhandledrejection", (event) => {
7276
- const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
7277
- this.sendError(error, { type: "promise" });
7278
- });
7279
- }
7280
- /**
7281
- * 设置兼容性函数
7282
- */
7283
- setupCompatibility() {
7284
- window.__SEND_ERROR_TO_PARENT__ = (error, details) => {
7285
- const errorObj = error instanceof Error ? error : new Error(String(error));
7286
- this.sendError(errorObj, details);
7287
- };
7288
- }
7289
- /**
7290
- * 发送错误到父窗口
7291
- */
7292
- sendError(error, details = {}) {
7293
- const payload = {
7294
- message: error.message,
7295
- stack: error.stack,
7296
- filename: details.filename || details.file,
7297
- lineno: details.lineno || details.line,
7298
- colno: details.colno || details.column,
7299
- timestamp: Date.now(),
7300
- type: details.type || "unknown",
7301
- severity: "medium",
7302
- // 简化版使用默认严重性级别
7303
- details
7304
- };
7305
- try {
7306
- this.sendMessage({
7307
- type: "ERROR_EVENT",
7308
- payload,
7309
- timestamp: Date.now()
7310
- });
7311
- } catch (e) {
7312
- const originalConsole = window.__originalConsole;
7313
- if (originalConsole?.error) {
7314
- originalConsole.error("[\u7B80\u5316\u9519\u8BEF\u5904\u7406] \u53D1\u9001\u5931\u8D25:", e);
7315
- }
7316
- }
7317
- }
7318
- /**
7319
- * 手动捕获错误
7320
- */
7321
- captureError(error, details) {
7322
- this.sendError(error, details);
7323
- }
7324
- };
7325
-
7326
3700
  // src/index.ts
7327
3701
  init_config();
7328
3702
 
@@ -7612,21 +3986,16 @@ var elementSelector = {
7612
3986
  AUTH_TOKEN_KEY,
7613
3987
  ClayxButton,
7614
3988
  ClayxToast,
7615
- DEFAULT_SELECTOR_CONFIG,
7616
3989
  DefaultErrorFallback,
7617
- ERROR_CONFIG,
7618
3990
  ElementSelector,
7619
3991
  ElementSelectorProvider,
7620
3992
  ErrorBoundary,
7621
- ErrorHandler,
7622
3993
  FloatingButton,
7623
- GLOBAL_CONFIG,
7624
3994
  GlobalToastContainer,
7625
3995
  HowOneProvider,
7626
3996
  Loading,
7627
3997
  LoadingSpinner,
7628
3998
  LoginForm,
7629
- SimpleErrorHandler,
7630
3999
  ThemeProvider,
7631
4000
  ThemeToggle,
7632
4001
  aiWorkflow,