@aiyiran/myclaw 1.1.154 → 1.1.156
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/assets/debug-collector.js +32 -7
- package/assets/debug-probe.js +38 -3
- package/package.json +1 -1
|
@@ -121,25 +121,40 @@ function appendDebugEvent(probeEvent) {
|
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
123
|
* 控制日志长度,避免无限膨胀。
|
|
124
|
+
*
|
|
125
|
+
* 关键约束:作品可能在循环里疯狂打 console.log(每帧几十条),若简单地"保留
|
|
126
|
+
* 最近 N 条",会让 console 噪音把 page-enter / 点击 / 按键 / 报错等关键事件
|
|
127
|
+
* 全部挤掉。所以这里分两档:
|
|
128
|
+
* - 关键事件(导航 / 交互 / 各类报错)优先全量保留;
|
|
129
|
+
* - console 只保留最近一批,给它单独的配额。
|
|
124
130
|
*/
|
|
125
131
|
function trimDebugEvents(events) {
|
|
126
132
|
if (events.length <= MAX_EVENTS) {
|
|
127
133
|
return;
|
|
128
134
|
}
|
|
129
135
|
|
|
130
|
-
const
|
|
136
|
+
const KEY_TYPES = new Set([
|
|
137
|
+
"probe-ready",
|
|
138
|
+
"page-enter",
|
|
139
|
+
"click",
|
|
140
|
+
"keydown",
|
|
131
141
|
"runtime-error",
|
|
132
142
|
"unhandledrejection",
|
|
133
|
-
"resource-error"
|
|
143
|
+
"resource-error",
|
|
144
|
+
"console-truncated"
|
|
134
145
|
]);
|
|
135
146
|
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
);
|
|
147
|
+
const keyEvents = events.filter((event) => KEY_TYPES.has(event.type));
|
|
148
|
+
const consoleEvents = events.filter((event) => !KEY_TYPES.has(event.type));
|
|
139
149
|
|
|
140
|
-
|
|
150
|
+
// console 配额 = 总上限减去关键事件占用,至少留一部分给 console。
|
|
151
|
+
const consoleQuota = Math.max(0, MAX_EVENTS - keyEvents.length);
|
|
152
|
+
const keptConsole = consoleEvents.slice(-consoleQuota);
|
|
141
153
|
|
|
142
|
-
|
|
154
|
+
// 合并后按 seq 还原时间顺序,再做去重。
|
|
155
|
+
const merged = [...keyEvents, ...keptConsole].sort(
|
|
156
|
+
(a, b) => (a.seq || 0) - (b.seq || 0)
|
|
157
|
+
);
|
|
143
158
|
|
|
144
159
|
const seen = new Set();
|
|
145
160
|
const deduped = [];
|
|
@@ -317,6 +332,16 @@ function renderDebugRecordPreview(record) {
|
|
|
317
332
|
function formatEventForStudent(event) {
|
|
318
333
|
const time = event.time ? event.time.slice(11, 19) : "";
|
|
319
334
|
|
|
335
|
+
if (event.type === "probe-ready") {
|
|
336
|
+
const version = event.payload && event.payload.probeVersion;
|
|
337
|
+
return `${time} 调试探针启动${version ? "(" + version + ")" : ""}`;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (event.type === "console-truncated") {
|
|
341
|
+
const limit = event.payload && event.payload.limit;
|
|
342
|
+
return `${time} 程序输出过多,已截断${limit ? "(上限 " + limit + " 条)" : ""}`;
|
|
343
|
+
}
|
|
344
|
+
|
|
320
345
|
if (event.type === "page-enter") {
|
|
321
346
|
return `${time} 进入页面:${event.pageTitle || event.pagePath || event.pageUrl}`;
|
|
322
347
|
}
|
package/assets/debug-probe.js
CHANGED
|
@@ -19,11 +19,18 @@
|
|
|
19
19
|
|
|
20
20
|
window.__OPENCLAW_DEBUG_PROBE_INSTALLED__ = true;
|
|
21
21
|
|
|
22
|
-
const PROBE_VERSION = "
|
|
22
|
+
const PROBE_VERSION = "probe_004";
|
|
23
23
|
const MAX_TEXT_LENGTH = 1000;
|
|
24
24
|
const MAX_STACK_LENGTH = 3000;
|
|
25
25
|
const MAX_ELEMENT_TEXT_LENGTH = 80;
|
|
26
26
|
|
|
27
|
+
// console 上报限流:作品可能在循环里疯狂打 log,无节制上报会刷爆父页面
|
|
28
|
+
// 的事件缓冲、把 page-enter / error 等关键事件挤掉。超过上限后停止上报
|
|
29
|
+
// console(其它类型不受影响),并补一条截断提示。
|
|
30
|
+
const MAX_CONSOLE_EVENTS = 100;
|
|
31
|
+
let _consoleEventCount = 0;
|
|
32
|
+
let _consoleTruncatedNotified = false;
|
|
33
|
+
|
|
27
34
|
function now() {
|
|
28
35
|
return new Date().toISOString();
|
|
29
36
|
}
|
|
@@ -222,11 +229,22 @@
|
|
|
222
229
|
original.apply(console, args);
|
|
223
230
|
} catch (error) {}
|
|
224
231
|
|
|
232
|
+
// error 级别始终上报(数量少且关键);log/warn 受限流约束。
|
|
233
|
+
if (level !== "error" && _consoleEventCount >= MAX_CONSOLE_EVENTS) {
|
|
234
|
+
if (!_consoleTruncatedNotified) {
|
|
235
|
+
_consoleTruncatedNotified = true;
|
|
236
|
+
sendEvent("console-truncated", { limit: MAX_CONSOLE_EVENTS });
|
|
237
|
+
}
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
225
241
|
try {
|
|
226
242
|
const stringArgs = args.map(function (arg) {
|
|
227
243
|
return truncate(safeStringify(arg), MAX_TEXT_LENGTH);
|
|
228
244
|
});
|
|
229
245
|
|
|
246
|
+
if (level !== "error") _consoleEventCount++;
|
|
247
|
+
|
|
230
248
|
sendEvent("console", {
|
|
231
249
|
level,
|
|
232
250
|
message: truncate(stringArgs.join(" "), MAX_TEXT_LENGTH),
|
|
@@ -237,11 +255,21 @@
|
|
|
237
255
|
});
|
|
238
256
|
}
|
|
239
257
|
|
|
240
|
-
// 去重:避免 setTimeout 拦截 和 window.error 事件
|
|
258
|
+
// 去重:避免 setTimeout 拦截 和 window.error 事件 重复上报同一个错误。
|
|
259
|
+
// 两条路径拿到的 message 不一致:setTimeout 拦截器拿到原始 error.message
|
|
260
|
+
// (如 "Cannot read..."),window error 事件则带 "Uncaught TypeError: " 前缀。
|
|
261
|
+
// 归一化时剥掉这个前缀,确保同一个错误只上报一次。
|
|
241
262
|
const _reportedErrorKeys = new Set();
|
|
242
263
|
|
|
264
|
+
function normalizeErrorKey(message) {
|
|
265
|
+
return truncate(
|
|
266
|
+
String(message || "").replace(/^Uncaught\s+(\w*Error)?:?\s*/i, ""),
|
|
267
|
+
200
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
243
271
|
function reportRuntimeError(message, filename, lineno, colno, stack) {
|
|
244
|
-
const key =
|
|
272
|
+
const key = normalizeErrorKey(message);
|
|
245
273
|
if (_reportedErrorKeys.has(key)) return;
|
|
246
274
|
_reportedErrorKeys.add(key);
|
|
247
275
|
sendEvent("runtime-error", {
|
|
@@ -361,6 +389,13 @@
|
|
|
361
389
|
setupClickListener();
|
|
362
390
|
setupKeydownListener();
|
|
363
391
|
|
|
392
|
+
// 启动标记:版本号 + 时间。
|
|
393
|
+
// - 独立页面:直接打到控制台,方便人工确认 probe 已就位、是哪个版本。
|
|
394
|
+
// - iframe 模式:作为本轮记录的明确起点事件,便于排查"是否新一轮"。
|
|
395
|
+
const startedAt = now();
|
|
396
|
+
_nativeLog("[PROBE] " + PROBE_VERSION + " 已启动 @ " + startedAt);
|
|
397
|
+
sendEvent("probe-ready", { probeVersion: PROBE_VERSION, startedAt });
|
|
398
|
+
|
|
364
399
|
if (document.readyState === "loading") {
|
|
365
400
|
document.addEventListener("DOMContentLoaded", sendPageEnter);
|
|
366
401
|
} else {
|