@aiyiran/myclaw 1.1.140 → 1.1.141
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/CLAUDE.md +25 -0
- package/assets/debug-collector.js +5 -0
- package/assets/myclaw-inject.js +395 -14
- package/index.js +9 -0
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -40,6 +40,31 @@ myclaw/
|
|
|
40
40
|
|
|
41
41
|
---
|
|
42
42
|
|
|
43
|
+
## 本地开发流程
|
|
44
|
+
|
|
45
|
+
**关键一步**:进仓库目录,跑一次 `npm link`(一次性)
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cd /Users/yiran/.openclaw/workspace-yiranclaw/myclaw
|
|
49
|
+
npm link
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
这会把 npm 包的符号链接指向你的 git 仓库,之后:
|
|
53
|
+
|
|
54
|
+
- 改了 `assets/`、`server/`、`patches/`、`index.js` 等任何文件
|
|
55
|
+
- 直接跑 `myclaw server` 或 `myclaw patch` —— 会用你改的代码,**无需 publish**
|
|
56
|
+
|
|
57
|
+
开发流程:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
修改代码 → mc server(重启同步) 或 mc patch(注入 control-ui)
|
|
61
|
+
→ 验证改动生效 → 改对了才 publish.sh --git
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**不 npm link 的后果**:改了代码要 publish + mc update 才能在 npm 包里生效,非常麻烦。
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
43
68
|
## 两个环境(本地 vs 远程)
|
|
44
69
|
|
|
45
70
|
很多逻辑都在这里分叉,改代码前先确认你在哪个环境:
|
|
@@ -179,6 +179,11 @@ async function closePreviewAndSaveDebugRecord() {
|
|
|
179
179
|
const result = await saveDebugRecordToServer(recordToSave);
|
|
180
180
|
|
|
181
181
|
latestDebugRecordResult = result;
|
|
182
|
+
window.myclawLastDebugRecord = {
|
|
183
|
+
...result,
|
|
184
|
+
workspace: currentWorkspaceContext && currentWorkspaceContext.workspace,
|
|
185
|
+
entryFile: currentWorkspaceContext && currentWorkspaceContext.entryFile,
|
|
186
|
+
};
|
|
182
187
|
|
|
183
188
|
setPreviewState("debug-record-ready");
|
|
184
189
|
|
package/assets/myclaw-inject.js
CHANGED
|
@@ -313,7 +313,340 @@
|
|
|
313
313
|
} catch (e) {}
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
// ═══ 3.
|
|
316
|
+
// ═══ 3. Debug 按钮 ═══
|
|
317
|
+
|
|
318
|
+
function createDebugButton() {
|
|
319
|
+
var btn = document.createElement("button");
|
|
320
|
+
btn.id = "myclaw-debug-btn";
|
|
321
|
+
btn.className = "agent-chat__input-btn";
|
|
322
|
+
btn.title = "Debug";
|
|
323
|
+
btn.setAttribute("aria-label", "Debug");
|
|
324
|
+
btn.innerHTML = [
|
|
325
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18"',
|
|
326
|
+
' viewBox="0 0 24 24" fill="none" stroke="currentColor"',
|
|
327
|
+
' stroke-width="2" stroke-linecap="round" stroke-linejoin="round">',
|
|
328
|
+
' <path d="m8 2 1.88 1.88"/>',
|
|
329
|
+
' <path d="M14.12 3.88 16 2"/>',
|
|
330
|
+
' <path d="M9 7.13v-1a3.003 3.003 0 1 1 6 0v1"/>',
|
|
331
|
+
' <path d="M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6"/>',
|
|
332
|
+
' <path d="M12 20v-9"/>',
|
|
333
|
+
' <path d="M6.53 9C4.6 9.43 3 11.3 3 13.5"/>',
|
|
334
|
+
' <path d="M20.97 13.5c0-2.2-1.6-4.07-3.53-4.5"/>',
|
|
335
|
+
' <path d="M4 19.5c0-2.2 1.8-4 4-4"/>',
|
|
336
|
+
' <path d="M20 19.5c0-2.2-1.8-4-4-4"/>',
|
|
337
|
+
'</svg>',
|
|
338
|
+
].join("");
|
|
339
|
+
|
|
340
|
+
btn.addEventListener("click", function (e) {
|
|
341
|
+
e.stopPropagation();
|
|
342
|
+
showDebugModal();
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
return btn;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
var debugVoiceDestroyers = [];
|
|
349
|
+
|
|
350
|
+
function closeDebugModal() {
|
|
351
|
+
debugVoiceDestroyers.forEach(function (destroy) {
|
|
352
|
+
try { destroy(); } catch (e) {}
|
|
353
|
+
});
|
|
354
|
+
debugVoiceDestroyers = [];
|
|
355
|
+
var modal = document.getElementById("myclaw-debug-modal");
|
|
356
|
+
if (modal) modal.remove();
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function makeDebugLabel(text) {
|
|
360
|
+
var label = document.createElement("div");
|
|
361
|
+
label.textContent = text;
|
|
362
|
+
label.className = "myclaw-debug-label";
|
|
363
|
+
return label;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function makeDebugVoiceInputField(placeholder, maxLength, onChange) {
|
|
367
|
+
var wrap = document.createElement("div");
|
|
368
|
+
wrap.style.cssText = [
|
|
369
|
+
"display:flex", "gap:8px", "align-items:center",
|
|
370
|
+
"width:100%", "box-sizing:border-box",
|
|
371
|
+
].join(";");
|
|
372
|
+
|
|
373
|
+
var input = document.createElement("textarea");
|
|
374
|
+
input.rows = 3;
|
|
375
|
+
input.maxLength = maxLength || 180;
|
|
376
|
+
input.placeholder = placeholder || "";
|
|
377
|
+
input.spellcheck = false;
|
|
378
|
+
input.style.cssText = [
|
|
379
|
+
"flex:1 1 0%", "min-width:0", "padding:9px 12px",
|
|
380
|
+
"background:#252536",
|
|
381
|
+
"border:1.5px solid #3d3d5c",
|
|
382
|
+
"border-radius:8px",
|
|
383
|
+
"color:#cdd6f4",
|
|
384
|
+
"font-size:13px",
|
|
385
|
+
"line-height:1.6",
|
|
386
|
+
"font-family:-apple-system,sans-serif",
|
|
387
|
+
"outline:none",
|
|
388
|
+
"resize:vertical",
|
|
389
|
+
"transition:border-color 0.15s, border-left-width 0.1s",
|
|
390
|
+
].join(";");
|
|
391
|
+
|
|
392
|
+
var localVoice = null;
|
|
393
|
+
var localRecording = false;
|
|
394
|
+
var localStopping = false;
|
|
395
|
+
|
|
396
|
+
input.onfocus = function () { if (!localRecording) input.style.borderColor = "#6366f1"; };
|
|
397
|
+
input.onblur = function () { if (!localRecording) input.style.borderColor = "#3d3d5c"; };
|
|
398
|
+
input.oninput = function () { if (onChange) onChange(input.value); };
|
|
399
|
+
|
|
400
|
+
var micBtn = document.createElement("button");
|
|
401
|
+
micBtn.type = "button";
|
|
402
|
+
micBtn.title = "语音输入";
|
|
403
|
+
micBtn.style.cssText = [
|
|
404
|
+
"width:34px", "height:34px", "flex-shrink:0",
|
|
405
|
+
"border-radius:50%",
|
|
406
|
+
"border:1.5px solid #3d3d5c",
|
|
407
|
+
"background:#252536",
|
|
408
|
+
"color:#888",
|
|
409
|
+
"cursor:pointer",
|
|
410
|
+
"display:flex", "align-items:center", "justify-content:center",
|
|
411
|
+
"transition:all 0.15s",
|
|
412
|
+
"position:relative",
|
|
413
|
+
].join(";");
|
|
414
|
+
micBtn.innerHTML = [
|
|
415
|
+
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none"',
|
|
416
|
+
' stroke="currentColor" stroke-width="2"',
|
|
417
|
+
' stroke-linecap="round" stroke-linejoin="round">',
|
|
418
|
+
' <path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/>',
|
|
419
|
+
' <path d="M19 10v2a7 7 0 0 1-14 0v-2"/>',
|
|
420
|
+
' <line x1="12" x2="12" y1="19" y2="22"/>',
|
|
421
|
+
'</svg>',
|
|
422
|
+
].join("");
|
|
423
|
+
|
|
424
|
+
function setMicUI(isRecording) {
|
|
425
|
+
if (isRecording) {
|
|
426
|
+
micBtn.style.background = "#ff4444";
|
|
427
|
+
micBtn.style.borderColor = "#ff4444";
|
|
428
|
+
micBtn.style.color = "#fff";
|
|
429
|
+
micBtn.title = "停止录音";
|
|
430
|
+
input.style.borderColor = "#ff4444";
|
|
431
|
+
input.style.borderLeftWidth = "3px";
|
|
432
|
+
} else {
|
|
433
|
+
micBtn.style.background = "#252536";
|
|
434
|
+
micBtn.style.borderColor = "#3d3d5c";
|
|
435
|
+
micBtn.style.color = "#888";
|
|
436
|
+
micBtn.title = "语音输入";
|
|
437
|
+
input.style.borderColor = "#3d3d5c";
|
|
438
|
+
input.style.borderLeftWidth = "1.5px";
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function initLocalVoice() {
|
|
443
|
+
if (typeof window.VoiceInput === "undefined") return false;
|
|
444
|
+
localVoice = new window.VoiceInput({
|
|
445
|
+
onResult: function (text) {
|
|
446
|
+
if (!localRecording && !localStopping) return;
|
|
447
|
+
input.value = String(text || "").slice(0, input.maxLength);
|
|
448
|
+
if (onChange) onChange(input.value);
|
|
449
|
+
},
|
|
450
|
+
onStatusChange: function (oldStatus, newStatus) {
|
|
451
|
+
if (newStatus === "idle" && localRecording && !localStopping) {
|
|
452
|
+
setTimeout(function () {
|
|
453
|
+
if (localRecording && localVoice) localVoice.start();
|
|
454
|
+
}, 300);
|
|
455
|
+
}
|
|
456
|
+
},
|
|
457
|
+
onError: function (err) {
|
|
458
|
+
console.error("[myclaw-debug] voice error:", err);
|
|
459
|
+
localRecording = false;
|
|
460
|
+
localStopping = false;
|
|
461
|
+
setMicUI(false);
|
|
462
|
+
},
|
|
463
|
+
});
|
|
464
|
+
return true;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function startLocalVoice() {
|
|
468
|
+
if (!localVoice && !initLocalVoice()) {
|
|
469
|
+
console.warn("[myclaw-debug] VoiceInput SDK 未加载");
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
localRecording = true;
|
|
473
|
+
setMicUI(true);
|
|
474
|
+
localVoice.start();
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function stopLocalVoice() {
|
|
478
|
+
if (!localRecording) return;
|
|
479
|
+
localStopping = true;
|
|
480
|
+
localRecording = false;
|
|
481
|
+
setMicUI(false);
|
|
482
|
+
setTimeout(function () {
|
|
483
|
+
localStopping = false;
|
|
484
|
+
if (localVoice) localVoice.stop();
|
|
485
|
+
}, 1500);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
micBtn.onclick = function () {
|
|
489
|
+
if (localRecording) {
|
|
490
|
+
stopLocalVoice();
|
|
491
|
+
} else {
|
|
492
|
+
startLocalVoice();
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
wrap.appendChild(input);
|
|
497
|
+
wrap.appendChild(micBtn);
|
|
498
|
+
|
|
499
|
+
return {
|
|
500
|
+
el: wrap,
|
|
501
|
+
getValue: function () { return input.value; },
|
|
502
|
+
focus: function () { input.focus(); },
|
|
503
|
+
destroy: function () { if (localRecording) stopLocalVoice(); },
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
function showDebugModal() {
|
|
508
|
+
if (document.getElementById("myclaw-debug-modal")) return;
|
|
509
|
+
|
|
510
|
+
var state = { description: "" };
|
|
511
|
+
|
|
512
|
+
function buildDebugPrompt() {
|
|
513
|
+
var rec = window.myclawLastDebugRecord;
|
|
514
|
+
var lines = [];
|
|
515
|
+
|
|
516
|
+
if (rec) {
|
|
517
|
+
if (rec.debugRecordPath) {
|
|
518
|
+
lines.push("调试记录文件:" + rec.debugRecordPath);
|
|
519
|
+
} else if (rec.debugRecordUrl) {
|
|
520
|
+
lines.push("调试记录:" + rec.debugRecordUrl);
|
|
521
|
+
} else if (rec.workspace) {
|
|
522
|
+
lines.push("调试记录:" + rec.workspace + "/debug/debug-record.html");
|
|
523
|
+
}
|
|
524
|
+
if (rec.entryFile) {
|
|
525
|
+
lines.push("正在调试的文件:" + rec.entryFile);
|
|
526
|
+
}
|
|
527
|
+
lines.push("");
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
lines.push("学生描述:" + (state.description || "(未填写)"));
|
|
531
|
+
lines.push("");
|
|
532
|
+
lines.push("请从学生描述里提取:我做了什么、发生了什么、我的预期是什么。");
|
|
533
|
+
lines.push("然后先阅读调试记录,再结合源码定位问题,只做最小修复。修复后说明原因和改动位置。");
|
|
534
|
+
|
|
535
|
+
return lines.join("\n");
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
var overlay = document.createElement("div");
|
|
539
|
+
overlay.id = "myclaw-debug-modal";
|
|
540
|
+
|
|
541
|
+
var box = document.createElement("div");
|
|
542
|
+
box.className = "myclaw-debug-box";
|
|
543
|
+
|
|
544
|
+
var header = document.createElement("div");
|
|
545
|
+
header.className = "myclaw-debug-header";
|
|
546
|
+
header.innerHTML = "<span>🐛 告诉 AI,发生了什么?</span>";
|
|
547
|
+
var closeX = document.createElement("span");
|
|
548
|
+
closeX.textContent = "✕";
|
|
549
|
+
closeX.className = "myclaw-debug-close";
|
|
550
|
+
closeX.onclick = function () { closeDebugModal(); };
|
|
551
|
+
header.appendChild(closeX);
|
|
552
|
+
|
|
553
|
+
var scroll = document.createElement("div");
|
|
554
|
+
scroll.className = "myclaw-debug-scroll";
|
|
555
|
+
|
|
556
|
+
var guide = document.createElement("div");
|
|
557
|
+
guide.className = "myclaw-debug-guide";
|
|
558
|
+
["我做了什么", "发生了什么", "我的预期是什么"].forEach(function (text) {
|
|
559
|
+
var item = document.createElement("span");
|
|
560
|
+
item.textContent = text;
|
|
561
|
+
guide.appendChild(item);
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
var inputSection = document.createElement("div");
|
|
565
|
+
inputSection.appendChild(makeDebugLabel("用一句话说清楚"));
|
|
566
|
+
var descriptionField = makeDebugVoiceInputField("比如:我点了开始按钮,页面没有反应,我希望角色开始移动", 180, function (val) {
|
|
567
|
+
state.description = val;
|
|
568
|
+
refresh();
|
|
569
|
+
});
|
|
570
|
+
inputSection.appendChild(descriptionField.el);
|
|
571
|
+
debugVoiceDestroyers.push(descriptionField.destroy);
|
|
572
|
+
|
|
573
|
+
var previewWrap = document.createElement("div");
|
|
574
|
+
previewWrap.className = "myclaw-debug-preview";
|
|
575
|
+
var previewLabel = document.createElement("div");
|
|
576
|
+
previewLabel.className = "myclaw-debug-preview-label";
|
|
577
|
+
previewLabel.textContent = "将要发给 AI 的内容:";
|
|
578
|
+
var previewEl = document.createElement("div");
|
|
579
|
+
previewEl.className = "myclaw-debug-preview-text";
|
|
580
|
+
previewWrap.appendChild(previewLabel);
|
|
581
|
+
previewWrap.appendChild(previewEl);
|
|
582
|
+
|
|
583
|
+
scroll.appendChild(guide);
|
|
584
|
+
scroll.appendChild(inputSection);
|
|
585
|
+
scroll.appendChild(previewWrap);
|
|
586
|
+
|
|
587
|
+
var footer = document.createElement("div");
|
|
588
|
+
footer.className = "myclaw-debug-footer";
|
|
589
|
+
|
|
590
|
+
var cancelBtn = document.createElement("button");
|
|
591
|
+
cancelBtn.className = "myclaw-debug-cancel";
|
|
592
|
+
cancelBtn.textContent = "取消";
|
|
593
|
+
cancelBtn.addEventListener("click", function () {
|
|
594
|
+
closeDebugModal();
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
var insertBtn = document.createElement("button");
|
|
598
|
+
insertBtn.className = "myclaw-debug-insert";
|
|
599
|
+
insertBtn.textContent = "⬇ 先放到聊天框";
|
|
600
|
+
insertBtn.addEventListener("click", function () {
|
|
601
|
+
if (!hasDebugInput()) return;
|
|
602
|
+
setTextareaValue(buildDebugPrompt());
|
|
603
|
+
closeDebugModal();
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
var submitBtn = document.createElement("button");
|
|
607
|
+
submitBtn.className = "myclaw-debug-submit";
|
|
608
|
+
submitBtn.textContent = "➤ 直接发给 AI";
|
|
609
|
+
submitBtn.addEventListener("click", function () {
|
|
610
|
+
if (!hasDebugInput()) return;
|
|
611
|
+
setTextareaValue(buildDebugPrompt());
|
|
612
|
+
closeDebugModal();
|
|
613
|
+
trySend();
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
function hasDebugInput() {
|
|
617
|
+
return !!state.description.trim();
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
function refresh() {
|
|
621
|
+
var ready = hasDebugInput();
|
|
622
|
+
previewEl.textContent = ready ? buildDebugPrompt() : "先写一项,这里会自动整理成要发给 AI 的内容。";
|
|
623
|
+
previewEl.style.color = ready ? "#cdd6f4" : "#555";
|
|
624
|
+
submitBtn.disabled = !ready;
|
|
625
|
+
insertBtn.disabled = !ready;
|
|
626
|
+
submitBtn.style.opacity = ready ? "1" : "0.4";
|
|
627
|
+
insertBtn.style.opacity = ready ? "1" : "0.4";
|
|
628
|
+
submitBtn.style.cursor = ready ? "pointer" : "not-allowed";
|
|
629
|
+
insertBtn.style.cursor = ready ? "pointer" : "not-allowed";
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
footer.appendChild(cancelBtn);
|
|
633
|
+
footer.appendChild(insertBtn);
|
|
634
|
+
footer.appendChild(submitBtn);
|
|
635
|
+
box.appendChild(header);
|
|
636
|
+
box.appendChild(scroll);
|
|
637
|
+
box.appendChild(footer);
|
|
638
|
+
overlay.appendChild(box);
|
|
639
|
+
document.body.appendChild(overlay);
|
|
640
|
+
|
|
641
|
+
overlay.addEventListener("click", function (e) {
|
|
642
|
+
if (e.target === overlay) closeDebugModal();
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
refresh();
|
|
646
|
+
descriptionField.focus();
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// ═══ 3.1 Prompt 小助手按钮(实现见 myclaw-iteration.js) ═══
|
|
317
650
|
|
|
318
651
|
function createPromptButton() {
|
|
319
652
|
return window.myclawIteration.createButton();
|
|
@@ -514,26 +847,31 @@ btn.addEventListener("click", function () {
|
|
|
514
847
|
|
|
515
848
|
function injectButton() {
|
|
516
849
|
var toolbar = document.querySelector(".agent-chat__toolbar-left");
|
|
517
|
-
if (!toolbar
|
|
850
|
+
if (!toolbar) return;
|
|
851
|
+
if (
|
|
852
|
+
toolbar.querySelector("#myclaw-debug-btn") &&
|
|
853
|
+
toolbar.querySelector("#myclaw-prompt-btn") &&
|
|
854
|
+
toolbar.querySelector("#myclaw-voice-btn")
|
|
855
|
+
) {
|
|
856
|
+
injected = true;
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
518
859
|
|
|
519
860
|
if (window.myclawIteration) {
|
|
520
861
|
window.myclawIteration.init({ trySend: trySend });
|
|
521
862
|
}
|
|
522
863
|
|
|
523
|
-
var
|
|
524
|
-
var promptBtn = createPromptButton();
|
|
864
|
+
var debugBtn = document.querySelector("#myclaw-debug-btn") || createDebugButton();
|
|
865
|
+
var promptBtn = document.querySelector("#myclaw-prompt-btn") || createPromptButton();
|
|
866
|
+
var voiceBtn = document.querySelector("#myclaw-voice-btn") || createVoiceButton();
|
|
525
867
|
|
|
526
|
-
// 插入到工具栏最前面:prompt
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
} else {
|
|
531
|
-
toolbar.appendChild(promptBtn);
|
|
532
|
-
toolbar.appendChild(voiceBtn);
|
|
533
|
-
}
|
|
868
|
+
// 插入到工具栏最前面:debug 按钮在最左,prompt 和语音按钮依次靠右
|
|
869
|
+
toolbar.insertBefore(voiceBtn, toolbar.firstChild);
|
|
870
|
+
toolbar.insertBefore(promptBtn, voiceBtn);
|
|
871
|
+
toolbar.insertBefore(debugBtn, promptBtn);
|
|
534
872
|
|
|
535
873
|
injected = true;
|
|
536
|
-
console.log("[myclaw-inject] \u2705 \u8bed\u97f3\u6309\u94ae + prompt\u6309\u94ae\u5df2\u6ce8\u5165");
|
|
874
|
+
console.log("[myclaw-inject] \u2705 debug\u6309\u94ae + \u8bed\u97f3\u6309\u94ae + prompt\u6309\u94ae\u5df2\u6ce8\u5165");
|
|
537
875
|
}
|
|
538
876
|
|
|
539
877
|
// ═══ 注入录音态样式 ═══
|
|
@@ -602,6 +940,45 @@ btn.addEventListener("click", function () {
|
|
|
602
940
|
" from { opacity: 0; }",
|
|
603
941
|
" to { opacity: 1; }",
|
|
604
942
|
"}",
|
|
943
|
+
/* Debug 提交弹框 */
|
|
944
|
+
"#myclaw-debug-modal {",
|
|
945
|
+
" position: fixed; inset: 0; z-index: 99999;",
|
|
946
|
+
" background: rgba(0,0,0,0.45);",
|
|
947
|
+
" display: flex; align-items: center; justify-content: center;",
|
|
948
|
+
" animation: myclaw-fade-in 0.15s ease;",
|
|
949
|
+
"}",
|
|
950
|
+
".myclaw-debug-box {",
|
|
951
|
+
" background: #fff; border-radius: 16px;",
|
|
952
|
+
" padding: 24px 28px 20px; width: 420px; max-width: 92vw;",
|
|
953
|
+
" box-shadow: 0 8px 32px rgba(0,0,0,0.18);",
|
|
954
|
+
" display: flex; flex-direction: column; gap: 12px;",
|
|
955
|
+
"}",
|
|
956
|
+
".myclaw-debug-title {",
|
|
957
|
+
" font-size: 18px; font-weight: 700; color: #222;",
|
|
958
|
+
"}",
|
|
959
|
+
".myclaw-debug-hint {",
|
|
960
|
+
" font-size: 13px; color: #888;",
|
|
961
|
+
"}",
|
|
962
|
+
".myclaw-debug-textarea {",
|
|
963
|
+
" width: 100%; box-sizing: border-box;",
|
|
964
|
+
" border: 1.5px solid #e0e0e0; border-radius: 10px;",
|
|
965
|
+
" padding: 12px; font-size: 14px; line-height: 1.7;",
|
|
966
|
+
" resize: vertical; outline: none; font-family: inherit; color: #333;",
|
|
967
|
+
"}",
|
|
968
|
+
".myclaw-debug-textarea:focus { border-color: #4f6ef7; }",
|
|
969
|
+
".myclaw-debug-footer {",
|
|
970
|
+
" display: flex; justify-content: flex-end; gap: 10px;",
|
|
971
|
+
"}",
|
|
972
|
+
".myclaw-debug-cancel {",
|
|
973
|
+
" padding: 8px 18px; border-radius: 8px; border: 1.5px solid #e0e0e0;",
|
|
974
|
+
" background: #fff; color: #666; font-size: 14px; cursor: pointer;",
|
|
975
|
+
"}",
|
|
976
|
+
".myclaw-debug-submit {",
|
|
977
|
+
" padding: 8px 20px; border-radius: 8px; border: none;",
|
|
978
|
+
" background: #4f6ef7; color: #fff; font-size: 14px;",
|
|
979
|
+
" font-weight: 600; cursor: pointer;",
|
|
980
|
+
"}",
|
|
981
|
+
".myclaw-debug-submit:hover { background: #3a58d6; }",
|
|
605
982
|
].join("\n");
|
|
606
983
|
document.head.appendChild(style);
|
|
607
984
|
}
|
|
@@ -1795,7 +2172,11 @@ btn.addEventListener("click", function () {
|
|
|
1795
2172
|
|
|
1796
2173
|
// 持续监听 DOM 变化,确保按钮始终在
|
|
1797
2174
|
new MutationObserver(function () {
|
|
1798
|
-
if (
|
|
2175
|
+
if (
|
|
2176
|
+
!document.querySelector("#myclaw-debug-btn") ||
|
|
2177
|
+
!document.querySelector("#myclaw-prompt-btn") ||
|
|
2178
|
+
!document.querySelector("#myclaw-voice-btn")
|
|
2179
|
+
) {
|
|
1799
2180
|
injected = false;
|
|
1800
2181
|
}
|
|
1801
2182
|
if (!injected) {
|
package/index.js
CHANGED
|
@@ -1986,16 +1986,21 @@ function runSync(workspaceName) {
|
|
|
1986
1986
|
|
|
1987
1987
|
// 用户目录下的服务目录
|
|
1988
1988
|
const targetDir = path.join(os.homedir(), '.openclaw', 'myclaw', 'server');
|
|
1989
|
+
const targetAssetsDir = path.join(os.homedir(), '.openclaw', 'myclaw', 'assets');
|
|
1989
1990
|
const targetPyPath = path.join(targetDir, 'sync_workspace.py');
|
|
1990
1991
|
const targetConfigPath = path.join(targetDir, 'config.json');
|
|
1991
1992
|
const sourcePyPath = path.join(__dirname, 'server', 'sync_workspace.py');
|
|
1992
1993
|
const sourceSchemaPath = path.join(__dirname, 'server', 'artifacts_schema.py');
|
|
1993
1994
|
const sourceDebugRecordPath = path.join(__dirname, 'server', 'debug_record.py');
|
|
1995
|
+
const sourceProbeJsPath = path.join(__dirname, 'assets', 'debug-probe.js');
|
|
1994
1996
|
|
|
1995
1997
|
// 确保目标目录存在
|
|
1996
1998
|
if (!fs.existsSync(targetDir)) {
|
|
1997
1999
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
1998
2000
|
}
|
|
2001
|
+
if (!fs.existsSync(targetAssetsDir)) {
|
|
2002
|
+
fs.mkdirSync(targetAssetsDir, { recursive: true });
|
|
2003
|
+
}
|
|
1999
2004
|
|
|
2000
2005
|
// 同步 py 文件
|
|
2001
2006
|
fs.copyFileSync(sourcePyPath, targetPyPath);
|
|
@@ -2003,6 +2008,10 @@ function runSync(workspaceName) {
|
|
|
2003
2008
|
if (fs.existsSync(sourceDebugRecordPath)) {
|
|
2004
2009
|
fs.copyFileSync(sourceDebugRecordPath, path.join(targetDir, 'debug_record.py'));
|
|
2005
2010
|
}
|
|
2011
|
+
// probe 源码:sync_workspace.py 注入 HTML 时需要读取它
|
|
2012
|
+
if (fs.existsSync(sourceProbeJsPath)) {
|
|
2013
|
+
fs.copyFileSync(sourceProbeJsPath, path.join(targetAssetsDir, 'debug-probe.js'));
|
|
2014
|
+
}
|
|
2006
2015
|
|
|
2007
2016
|
// 读取配置(如果不存在则创建)
|
|
2008
2017
|
let config;
|