@aiyiran/myclaw 1.1.75 → 1.1.77
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/myclaw-artifacts.js +5 -1
- package/assets/myclaw-inject.js +26 -502
- package/assets/myclaw-iteration.js +652 -0
- package/package.json +1 -1
- package/patches/patch.js +19 -0
- package/skills/yiran-course-template-pipeline/scripts/build_template_views.py +7 -0
- package/skills/yiran-course-template-pipeline/template-index.json +54 -1
- package/skills/yiran-course-template-pipeline/template-index.md +18 -0
- package/skills/yiran-playground-template-use/SKILL.md +1 -1
- package/skills/yiran-playground-template-use/prompts/remix-handoff.txt +14 -5
|
@@ -1664,7 +1664,11 @@
|
|
|
1664
1664
|
entryDefaultOpt.value = '';
|
|
1665
1665
|
entryDefaultOpt.textContent = '选择作品的网页入口文件';
|
|
1666
1666
|
entrySelect.appendChild(entryDefaultOpt);
|
|
1667
|
-
var htmlAssets = (cachedData.assets || []).filter(function (a) {
|
|
1667
|
+
var htmlAssets = (cachedData.assets || []).filter(function (a) {
|
|
1668
|
+
if (!(a.type && a.type.toLowerCase() === 'html')) return false;
|
|
1669
|
+
var filename = a.path.split('/').pop();
|
|
1670
|
+
return !filename.startsWith('__');
|
|
1671
|
+
});
|
|
1668
1672
|
htmlAssets.forEach(function (asset) {
|
|
1669
1673
|
var opt = document.createElement('option');
|
|
1670
1674
|
opt.value = asset.path;
|
package/assets/myclaw-inject.js
CHANGED
|
@@ -313,507 +313,10 @@
|
|
|
313
313
|
} catch (e) {}
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
// ═══ 3. Prompt
|
|
317
|
-
|
|
318
|
-
var promptOpen = false;
|
|
319
|
-
var modalVoiceDestroy = null; // 弹框内语音组件的销毁函数
|
|
316
|
+
// ═══ 3. Prompt 小助手按钮(实现见 myclaw-iteration.js) ═══
|
|
320
317
|
|
|
321
318
|
function createPromptButton() {
|
|
322
|
-
|
|
323
|
-
btn.id = "myclaw-prompt-btn";
|
|
324
|
-
btn.className = "agent-chat__input-btn";
|
|
325
|
-
btn.title = "\u63d0\u95ee prompt \u5c0f\u52a9\u624b";
|
|
326
|
-
btn.setAttribute("aria-label", "\u63d0\u95ee prompt \u5c0f\u52a9\u624b");
|
|
327
|
-
btn.innerHTML = [
|
|
328
|
-
'<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18"',
|
|
329
|
-
' viewBox="0 0 24 24" fill="none" stroke="currentColor"',
|
|
330
|
-
' stroke-width="2" stroke-linecap="round" stroke-linejoin="round">',
|
|
331
|
-
' <circle cx="12" cy="12" r="10"/>',
|
|
332
|
-
' <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/>',
|
|
333
|
-
' <line x1="12" y1="17" x2="12.01" y2="17"/>',
|
|
334
|
-
'</svg>',
|
|
335
|
-
].join("");
|
|
336
|
-
|
|
337
|
-
btn.addEventListener("click", function (e) {
|
|
338
|
-
e.stopPropagation();
|
|
339
|
-
if (promptOpen) {
|
|
340
|
-
closePromptModal();
|
|
341
|
-
} else {
|
|
342
|
-
openPromptModal();
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
return btn;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// ── 文案配置(集中管理,方便后续修改) ──
|
|
350
|
-
|
|
351
|
-
var ITERATION_CONFIG = {
|
|
352
|
-
problems: ["不好看", "不好玩", "太简单", "不清楚", "没反应", "不像我想的", "太乱了", "不知道接下来做什么"],
|
|
353
|
-
actions: ["加一个新东西", "改一下样子", "改一下内容", "改一下功能", "让它动起来", "让它更有趣", "让它更清楚", "先做一个最简单的新版本"],
|
|
354
|
-
};
|
|
355
|
-
|
|
356
|
-
function openPromptModal() {
|
|
357
|
-
if (document.querySelector("#myclaw-prompt-modal")) return;
|
|
358
|
-
promptOpen = true;
|
|
359
|
-
|
|
360
|
-
var iconBtn = document.querySelector("#myclaw-prompt-btn");
|
|
361
|
-
if (iconBtn) iconBtn.style.color = "#6366f1";
|
|
362
|
-
|
|
363
|
-
// ── 状态(关闭即清空) ──
|
|
364
|
-
var state = { problem: "", action: "", note: "" };
|
|
365
|
-
|
|
366
|
-
// ── 文本生成 ──
|
|
367
|
-
function buildText() {
|
|
368
|
-
if (!state.problem || !state.action) return "";
|
|
369
|
-
var t = "我现在这个作品的问题是【" + state.problem + "】。\n"
|
|
370
|
-
+ "我下一步想先【" + state.action + "】。\n"
|
|
371
|
-
+ "请根据我当前正在做的内容,帮我只改一个点,给我一个最简单、最容易成功的下一步方案。";
|
|
372
|
-
if (state.note.trim()) t += "\n补充说明:" + state.note.trim();
|
|
373
|
-
return t;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
function buildPayload() {
|
|
377
|
-
return {
|
|
378
|
-
type: "iteration_helper",
|
|
379
|
-
problem: state.problem,
|
|
380
|
-
next_action: state.action,
|
|
381
|
-
extra_note: state.note,
|
|
382
|
-
generated_text: buildText(),
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
// ── 刷新预览 & 按钮可用性 ──
|
|
387
|
-
var previewEl, actionSendBtn, actionInsertBtn;
|
|
388
|
-
function refresh() {
|
|
389
|
-
var text = buildText();
|
|
390
|
-
var ready = !!(state.problem && state.action);
|
|
391
|
-
if (previewEl) {
|
|
392
|
-
previewEl.textContent = text || "先选上面两项,这里会自动生成要发给 AI 的内容 ✨";
|
|
393
|
-
previewEl.style.color = ready ? "#cdd6f4" : "#555";
|
|
394
|
-
}
|
|
395
|
-
if (actionSendBtn) {
|
|
396
|
-
actionSendBtn.disabled = !ready;
|
|
397
|
-
actionSendBtn.style.opacity = ready ? "1" : "0.4";
|
|
398
|
-
actionSendBtn.style.cursor = ready ? "pointer" : "not-allowed";
|
|
399
|
-
}
|
|
400
|
-
if (actionInsertBtn) {
|
|
401
|
-
actionInsertBtn.disabled = !ready;
|
|
402
|
-
actionInsertBtn.style.opacity = ready ? "1" : "0.4";
|
|
403
|
-
actionInsertBtn.style.cursor = ready ? "pointer" : "not-allowed";
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// ── 芯片选择组(单选,再点可取消) ──
|
|
408
|
-
function makeChipGroup(items, activeColor, onChange) {
|
|
409
|
-
var wrap = document.createElement("div");
|
|
410
|
-
wrap.style.cssText = "display:flex;flex-wrap:wrap;gap:7px;";
|
|
411
|
-
var chips = [];
|
|
412
|
-
items.forEach(function (label) {
|
|
413
|
-
var chip = document.createElement("button");
|
|
414
|
-
chip.textContent = label;
|
|
415
|
-
chip.dataset.selected = "0";
|
|
416
|
-
chip.style.cssText = [
|
|
417
|
-
"padding:6px 13px",
|
|
418
|
-
"border-radius:20px",
|
|
419
|
-
"border:1.5px solid #3d3d5c",
|
|
420
|
-
"background:#252536",
|
|
421
|
-
"color:#888",
|
|
422
|
-
"font-size:13px",
|
|
423
|
-
"font-family:-apple-system,sans-serif",
|
|
424
|
-
"cursor:pointer",
|
|
425
|
-
"transition:all 0.15s",
|
|
426
|
-
"white-space:nowrap",
|
|
427
|
-
].join(";");
|
|
428
|
-
|
|
429
|
-
function applyStyle(sel) {
|
|
430
|
-
if (sel) {
|
|
431
|
-
chip.style.background = activeColor;
|
|
432
|
-
chip.style.borderColor = activeColor;
|
|
433
|
-
chip.style.color = "#fff";
|
|
434
|
-
chip.style.fontWeight = "bold";
|
|
435
|
-
} else {
|
|
436
|
-
chip.style.background = "#252536";
|
|
437
|
-
chip.style.borderColor = "#3d3d5c";
|
|
438
|
-
chip.style.color = "#888";
|
|
439
|
-
chip.style.fontWeight = "normal";
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
chip.onmouseenter = function () {
|
|
444
|
-
if (chip.dataset.selected !== "1") chip.style.borderColor = activeColor;
|
|
445
|
-
};
|
|
446
|
-
chip.onmouseleave = function () {
|
|
447
|
-
if (chip.dataset.selected !== "1") chip.style.borderColor = "#3d3d5c";
|
|
448
|
-
};
|
|
449
|
-
chip.onclick = function () {
|
|
450
|
-
var nowOn = chip.dataset.selected !== "1";
|
|
451
|
-
// 取消同组其他
|
|
452
|
-
chips.forEach(function (c) { c.dataset.selected = "0"; applyStyle.call({chip:c}, false); });
|
|
453
|
-
// 重新用当前 chip 的 applyStyle(通过闭包拿到正确 chip)
|
|
454
|
-
chips.forEach(function (c) {
|
|
455
|
-
if (c !== chip) {
|
|
456
|
-
c.style.background = "#252536";
|
|
457
|
-
c.style.borderColor = "#3d3d5c";
|
|
458
|
-
c.style.color = "#888";
|
|
459
|
-
c.style.fontWeight = "normal";
|
|
460
|
-
c.dataset.selected = "0";
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
chip.dataset.selected = nowOn ? "1" : "0";
|
|
464
|
-
applyStyle(nowOn);
|
|
465
|
-
onChange(nowOn ? label : "");
|
|
466
|
-
};
|
|
467
|
-
|
|
468
|
-
chips.push(chip);
|
|
469
|
-
wrap.appendChild(chip);
|
|
470
|
-
});
|
|
471
|
-
return wrap;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
// ── 区域标题 ──
|
|
475
|
-
function makeLabel(text) {
|
|
476
|
-
var el = document.createElement("div");
|
|
477
|
-
el.textContent = text;
|
|
478
|
-
el.style.cssText = "font-size:13px;font-weight:bold;color:#cdd6f4;margin-bottom:8px;font-family:-apple-system,sans-serif;";
|
|
479
|
-
return el;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
// ══════════ DOM 组装 ══════════
|
|
483
|
-
|
|
484
|
-
// 遮罩
|
|
485
|
-
var overlay = document.createElement("div");
|
|
486
|
-
overlay.id = "myclaw-prompt-modal";
|
|
487
|
-
overlay.style.cssText = [
|
|
488
|
-
"position:fixed", "top:0", "left:0",
|
|
489
|
-
"width:100vw", "height:100vh",
|
|
490
|
-
"background:rgba(0,0,0,0.45)",
|
|
491
|
-
"z-index:99998",
|
|
492
|
-
"display:flex", "align-items:center", "justify-content:center",
|
|
493
|
-
"animation:myclaw-fade-in 0.15s ease",
|
|
494
|
-
].join(";");
|
|
495
|
-
|
|
496
|
-
// 弹框
|
|
497
|
-
var box = document.createElement("div");
|
|
498
|
-
box.style.cssText = [
|
|
499
|
-
"width:560px", "max-width:96vw", "max-height:92vh",
|
|
500
|
-
"background:#1e1e2e",
|
|
501
|
-
"border-radius:12px",
|
|
502
|
-
"overflow:hidden",
|
|
503
|
-
"display:flex", "flex-direction:column",
|
|
504
|
-
"box-shadow:0 12px 48px rgba(0,0,0,0.6)",
|
|
505
|
-
].join(";");
|
|
506
|
-
|
|
507
|
-
// 标题栏
|
|
508
|
-
var header = document.createElement("div");
|
|
509
|
-
header.style.cssText = [
|
|
510
|
-
"display:flex", "align-items:center", "justify-content:space-between",
|
|
511
|
-
"padding:13px 18px",
|
|
512
|
-
"background:linear-gradient(135deg,#6366f1,#8b5cf6)",
|
|
513
|
-
"color:#fff",
|
|
514
|
-
"font-size:15px", "font-weight:bold",
|
|
515
|
-
"font-family:-apple-system,sans-serif",
|
|
516
|
-
"user-select:none", "flex-shrink:0",
|
|
517
|
-
].join(";");
|
|
518
|
-
header.innerHTML = "<span>🤔 我卡住了,帮我继续改</span>";
|
|
519
|
-
var closeX = document.createElement("span");
|
|
520
|
-
closeX.textContent = "✕";
|
|
521
|
-
closeX.style.cssText = "cursor:pointer;padding:2px 8px;border-radius:4px;font-size:15px;transition:background 0.15s;";
|
|
522
|
-
closeX.onmouseenter = function () { closeX.style.background = "rgba(255,255,255,0.2)"; };
|
|
523
|
-
closeX.onmouseleave = function () { closeX.style.background = "none"; };
|
|
524
|
-
closeX.onclick = function () { closePromptModal(); };
|
|
525
|
-
header.appendChild(closeX);
|
|
526
|
-
|
|
527
|
-
// 滚动内容区
|
|
528
|
-
var scroll = document.createElement("div");
|
|
529
|
-
scroll.style.cssText = "flex:1;overflow-y:auto;padding:20px 20px 8px;display:flex;flex-direction:column;gap:20px;";
|
|
530
|
-
|
|
531
|
-
// ── 第1区:问题 ──
|
|
532
|
-
var sec1 = document.createElement("div");
|
|
533
|
-
sec1.appendChild(makeLabel("现在最想改的问题是?"));
|
|
534
|
-
sec1.appendChild(makeChipGroup(ITERATION_CONFIG.problems, "#f59e0b", function (val) {
|
|
535
|
-
state.problem = val; refresh();
|
|
536
|
-
}));
|
|
537
|
-
scroll.appendChild(sec1);
|
|
538
|
-
|
|
539
|
-
// ── 第2区:行动 ──
|
|
540
|
-
var sec2 = document.createElement("div");
|
|
541
|
-
sec2.appendChild(makeLabel("你下一步想先改什么?"));
|
|
542
|
-
sec2.appendChild(makeChipGroup(ITERATION_CONFIG.actions, "#6366f1", function (val) {
|
|
543
|
-
state.action = val; refresh();
|
|
544
|
-
}));
|
|
545
|
-
scroll.appendChild(sec2);
|
|
546
|
-
|
|
547
|
-
// ── 第3区:补充(带语音输入) ──
|
|
548
|
-
var sec3 = document.createElement("div");
|
|
549
|
-
sec3.appendChild(makeLabel("可以补充一点点(可不填)"));
|
|
550
|
-
var placeholders = ["比如:我想做成飞行射击", "比如:我想更像小猫主题", "比如:按钮点了以后想有变化"];
|
|
551
|
-
var noteField = makeVoiceInputField(
|
|
552
|
-
placeholders[Math.floor(Math.random() * placeholders.length)],
|
|
553
|
-
60,
|
|
554
|
-
function (val) { state.note = val; refresh(); }
|
|
555
|
-
);
|
|
556
|
-
modalVoiceDestroy = noteField.destroy;
|
|
557
|
-
sec3.appendChild(noteField.el);
|
|
558
|
-
scroll.appendChild(sec3);
|
|
559
|
-
|
|
560
|
-
// ── 预览区 ──
|
|
561
|
-
var previewWrap = document.createElement("div");
|
|
562
|
-
previewWrap.style.cssText = [
|
|
563
|
-
"padding:12px 14px",
|
|
564
|
-
"background:#252536",
|
|
565
|
-
"border-radius:8px",
|
|
566
|
-
"border-left:3px solid #6366f1",
|
|
567
|
-
].join(";");
|
|
568
|
-
var previewLabel = document.createElement("div");
|
|
569
|
-
previewLabel.textContent = "将要发给 AI 的内容:";
|
|
570
|
-
previewLabel.style.cssText = "font-size:11px;color:#6366f1;font-weight:bold;margin-bottom:6px;font-family:monospace;letter-spacing:0.3px;";
|
|
571
|
-
previewEl = document.createElement("div");
|
|
572
|
-
previewEl.style.cssText = "font-size:13px;line-height:1.7;white-space:pre-wrap;font-family:-apple-system,sans-serif;word-break:break-all;";
|
|
573
|
-
previewWrap.appendChild(previewLabel);
|
|
574
|
-
previewWrap.appendChild(previewEl);
|
|
575
|
-
scroll.appendChild(previewWrap);
|
|
576
|
-
|
|
577
|
-
// ── 底部按钮区 ──
|
|
578
|
-
var footer = document.createElement("div");
|
|
579
|
-
footer.style.cssText = [
|
|
580
|
-
"display:flex", "gap:10px",
|
|
581
|
-
"padding:14px 20px",
|
|
582
|
-
"border-top:1px solid #2d2d3f",
|
|
583
|
-
"flex-shrink:0",
|
|
584
|
-
"background:#1e1e2e",
|
|
585
|
-
].join(";");
|
|
586
|
-
|
|
587
|
-
actionSendBtn = document.createElement("button");
|
|
588
|
-
actionSendBtn.textContent = "➤ 直接发给 AI";
|
|
589
|
-
actionSendBtn.disabled = true;
|
|
590
|
-
actionSendBtn.style.cssText = [
|
|
591
|
-
"flex:1", "padding:11px 0",
|
|
592
|
-
"background:#10b981", "color:#fff",
|
|
593
|
-
"border:none", "border-radius:8px",
|
|
594
|
-
"font-size:14px", "font-weight:bold",
|
|
595
|
-
"font-family:-apple-system,sans-serif",
|
|
596
|
-
"cursor:not-allowed", "transition:all 0.15s", "opacity:0.4",
|
|
597
|
-
].join(";");
|
|
598
|
-
actionSendBtn.onmouseenter = function () { if (!actionSendBtn.disabled) actionSendBtn.style.background = "#059669"; };
|
|
599
|
-
actionSendBtn.onmouseleave = function () { if (!actionSendBtn.disabled) actionSendBtn.style.background = "#10b981"; };
|
|
600
|
-
actionSendBtn.onclick = function () {
|
|
601
|
-
if (actionSendBtn.disabled) return;
|
|
602
|
-
var payload = buildPayload();
|
|
603
|
-
console.log("[myclaw-prompt] onSendDirect", payload);
|
|
604
|
-
insertPromptText(payload.generated_text);
|
|
605
|
-
closePromptModal();
|
|
606
|
-
setTimeout(function () { trySend(); }, 50);
|
|
607
|
-
};
|
|
608
|
-
|
|
609
|
-
actionInsertBtn = document.createElement("button");
|
|
610
|
-
actionInsertBtn.textContent = "⬇ 先放到聊天框";
|
|
611
|
-
actionInsertBtn.disabled = true;
|
|
612
|
-
actionInsertBtn.style.cssText = [
|
|
613
|
-
"flex:1", "padding:11px 0",
|
|
614
|
-
"background:#6366f1", "color:#fff",
|
|
615
|
-
"border:none", "border-radius:8px",
|
|
616
|
-
"font-size:14px", "font-weight:bold",
|
|
617
|
-
"font-family:-apple-system,sans-serif",
|
|
618
|
-
"cursor:not-allowed", "transition:all 0.15s", "opacity:0.4",
|
|
619
|
-
].join(";");
|
|
620
|
-
actionInsertBtn.onmouseenter = function () { if (!actionInsertBtn.disabled) actionInsertBtn.style.background = "#4f46e5"; };
|
|
621
|
-
actionInsertBtn.onmouseleave = function () { if (!actionInsertBtn.disabled) actionInsertBtn.style.background = "#6366f1"; };
|
|
622
|
-
actionInsertBtn.onclick = function () {
|
|
623
|
-
if (actionInsertBtn.disabled) return;
|
|
624
|
-
var payload = buildPayload();
|
|
625
|
-
console.log("[myclaw-prompt] onInsertToInput", payload);
|
|
626
|
-
insertPromptText(payload.generated_text);
|
|
627
|
-
closePromptModal();
|
|
628
|
-
};
|
|
629
|
-
|
|
630
|
-
footer.appendChild(actionSendBtn);
|
|
631
|
-
footer.appendChild(actionInsertBtn);
|
|
632
|
-
|
|
633
|
-
// ── 拼装 ──
|
|
634
|
-
box.appendChild(header);
|
|
635
|
-
box.appendChild(scroll);
|
|
636
|
-
box.appendChild(footer);
|
|
637
|
-
overlay.appendChild(box);
|
|
638
|
-
overlay.onclick = function (e) { if (e.target === overlay) closePromptModal(); };
|
|
639
|
-
document.body.appendChild(overlay);
|
|
640
|
-
|
|
641
|
-
refresh();
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
function closePromptModal() {
|
|
645
|
-
if (modalVoiceDestroy) { modalVoiceDestroy(); modalVoiceDestroy = null; }
|
|
646
|
-
var modal = document.querySelector("#myclaw-prompt-modal");
|
|
647
|
-
if (modal) modal.remove();
|
|
648
|
-
promptOpen = false;
|
|
649
|
-
|
|
650
|
-
var btn = document.querySelector("#myclaw-prompt-btn");
|
|
651
|
-
if (btn) { btn.style.color = ""; }
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
/**
|
|
655
|
-
* 在 textarea 光标处插入 prompt 文字
|
|
656
|
-
*/
|
|
657
|
-
function insertPromptText(text) {
|
|
658
|
-
var ta = document.querySelector(".agent-chat__input textarea");
|
|
659
|
-
if (!ta) return;
|
|
660
|
-
|
|
661
|
-
var start = ta.selectionStart || 0;
|
|
662
|
-
var end = ta.selectionEnd || 0;
|
|
663
|
-
var current = ta.value;
|
|
664
|
-
var newValue = current.substring(0, start) + text + current.substring(end);
|
|
665
|
-
|
|
666
|
-
var setter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value").set;
|
|
667
|
-
setter.call(ta, newValue);
|
|
668
|
-
ta.dispatchEvent(new Event("input", { bubbles: true }));
|
|
669
|
-
|
|
670
|
-
var newCursor = start + text.length;
|
|
671
|
-
try { ta.setSelectionRange(newCursor, newCursor); } catch (e) {}
|
|
672
|
-
ta.focus();
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
// ═══ 3.6 带语音的输入框组件 ═══
|
|
676
|
-
|
|
677
|
-
/**
|
|
678
|
-
* makeVoiceInputField(placeholder, maxLength, onChange)
|
|
679
|
-
* 返回 { el, getValue, setValue, destroy }
|
|
680
|
-
*
|
|
681
|
-
* 完全独立:有自己的 VoiceInput 实例和录音状态,
|
|
682
|
-
* 不污染主 recording / voice 全局变量。
|
|
683
|
-
*/
|
|
684
|
-
function makeVoiceInputField(placeholder, maxLength, onChange) {
|
|
685
|
-
var lVoice = null; // 本组件的 VoiceInput 实例
|
|
686
|
-
var lRecording = false; // 本组件的录音状态
|
|
687
|
-
var lStopping = false; // 本组件的 stopping 窗口
|
|
688
|
-
|
|
689
|
-
// ── 容器 ──
|
|
690
|
-
var wrap = document.createElement("div");
|
|
691
|
-
wrap.style.cssText = "display:flex;gap:8px;align-items:center;width:100%;box-sizing:border-box;";
|
|
692
|
-
|
|
693
|
-
// ── 输入框 ──
|
|
694
|
-
var input = document.createElement("input");
|
|
695
|
-
input.type = "text";
|
|
696
|
-
input.maxLength = maxLength || 60;
|
|
697
|
-
input.placeholder = placeholder || "";
|
|
698
|
-
input.style.cssText = [
|
|
699
|
-
"flex:1", "min-width:0", "padding:9px 12px",
|
|
700
|
-
"background:#252536",
|
|
701
|
-
"border:1.5px solid #3d3d5c",
|
|
702
|
-
"border-radius:8px",
|
|
703
|
-
"color:#cdd6f4",
|
|
704
|
-
"font-size:13px",
|
|
705
|
-
"font-family:-apple-system,sans-serif",
|
|
706
|
-
"outline:none",
|
|
707
|
-
"transition:border-color 0.15s, border-left-width 0.1s",
|
|
708
|
-
].join(";");
|
|
709
|
-
input.onfocus = function () { if (!lRecording) input.style.borderColor = "#6366f1"; };
|
|
710
|
-
input.onblur = function () { if (!lRecording) input.style.borderColor = "#3d3d5c"; };
|
|
711
|
-
input.oninput = function () { if (onChange) onChange(input.value); };
|
|
712
|
-
|
|
713
|
-
// ── 麦克风按钮 ──
|
|
714
|
-
var micBtn = document.createElement("button");
|
|
715
|
-
micBtn.type = "button";
|
|
716
|
-
micBtn.title = "语音输入";
|
|
717
|
-
micBtn.style.cssText = [
|
|
718
|
-
"width:34px", "height:34px", "flex-shrink:0",
|
|
719
|
-
"border-radius:50%",
|
|
720
|
-
"border:1.5px solid #3d3d5c",
|
|
721
|
-
"background:#252536",
|
|
722
|
-
"color:#888",
|
|
723
|
-
"cursor:pointer",
|
|
724
|
-
"display:flex", "align-items:center", "justify-content:center",
|
|
725
|
-
"transition:all 0.15s",
|
|
726
|
-
"position:relative",
|
|
727
|
-
].join(";");
|
|
728
|
-
micBtn.innerHTML = [
|
|
729
|
-
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none"',
|
|
730
|
-
' stroke="currentColor" stroke-width="2"',
|
|
731
|
-
' stroke-linecap="round" stroke-linejoin="round">',
|
|
732
|
-
' <path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/>',
|
|
733
|
-
' <path d="M19 10v2a7 7 0 0 1-14 0v-2"/>',
|
|
734
|
-
' <line x1="12" x2="12" y1="19" y2="22"/>',
|
|
735
|
-
'</svg>',
|
|
736
|
-
].join("");
|
|
737
|
-
|
|
738
|
-
// ── UI 状态切换 ──
|
|
739
|
-
function setUI(recording) {
|
|
740
|
-
if (recording) {
|
|
741
|
-
micBtn.style.background = "#ff4444";
|
|
742
|
-
micBtn.style.borderColor = "#ff4444";
|
|
743
|
-
micBtn.style.color = "#fff";
|
|
744
|
-
micBtn.title = "停止录音";
|
|
745
|
-
input.style.borderColor = "#ff4444";
|
|
746
|
-
input.style.borderLeftWidth = "3px";
|
|
747
|
-
} else {
|
|
748
|
-
micBtn.style.background = "#252536";
|
|
749
|
-
micBtn.style.borderColor = "#3d3d5c";
|
|
750
|
-
micBtn.style.color = "#888";
|
|
751
|
-
micBtn.title = "语音输入";
|
|
752
|
-
input.style.borderColor = "#3d3d5c";
|
|
753
|
-
input.style.borderLeftWidth = "1.5px";
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
// ── 初始化本组件的 VoiceInput 实例 ──
|
|
758
|
-
function initLVoice() {
|
|
759
|
-
if (typeof window.VoiceInput === "undefined") return false;
|
|
760
|
-
lVoice = new window.VoiceInput({
|
|
761
|
-
onResult: function (text) {
|
|
762
|
-
if (!lRecording && !lStopping) return;
|
|
763
|
-
input.value = text;
|
|
764
|
-
if (onChange) onChange(text);
|
|
765
|
-
},
|
|
766
|
-
onStatusChange: function (oldS, newS) {
|
|
767
|
-
// 讯飞 60s 断开 → 自动重连
|
|
768
|
-
if (newS === "idle" && lRecording && !lStopping) {
|
|
769
|
-
setTimeout(function () {
|
|
770
|
-
if (lRecording && lVoice) lVoice.start();
|
|
771
|
-
}, 300);
|
|
772
|
-
}
|
|
773
|
-
},
|
|
774
|
-
onError: function (err) {
|
|
775
|
-
console.error("[voice-input-field] error:", err);
|
|
776
|
-
lRecording = false; lStopping = false;
|
|
777
|
-
setUI(false);
|
|
778
|
-
},
|
|
779
|
-
});
|
|
780
|
-
return true;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
function startLocal() {
|
|
784
|
-
if (!lVoice && !initLVoice()) {
|
|
785
|
-
console.warn("[voice-input-field] VoiceInput SDK 未加载");
|
|
786
|
-
return;
|
|
787
|
-
}
|
|
788
|
-
lRecording = true;
|
|
789
|
-
setUI(true);
|
|
790
|
-
lVoice.start();
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
function stopLocal() {
|
|
794
|
-
if (!lRecording) return;
|
|
795
|
-
lStopping = true;
|
|
796
|
-
lRecording = false;
|
|
797
|
-
setUI(false);
|
|
798
|
-
setTimeout(function () {
|
|
799
|
-
lStopping = false;
|
|
800
|
-
if (lVoice) lVoice.stop();
|
|
801
|
-
}, 1500);
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
micBtn.onclick = function () {
|
|
805
|
-
if (lRecording) { stopLocal(); } else { startLocal(); }
|
|
806
|
-
};
|
|
807
|
-
|
|
808
|
-
wrap.appendChild(input);
|
|
809
|
-
wrap.appendChild(micBtn);
|
|
810
|
-
|
|
811
|
-
return {
|
|
812
|
-
el: wrap,
|
|
813
|
-
getValue: function () { return input.value; },
|
|
814
|
-
setValue: function (v) { input.value = v; if (onChange) onChange(v); },
|
|
815
|
-
destroy: function () { if (lRecording) stopLocal(); },
|
|
816
|
-
};
|
|
319
|
+
return window.myclawIteration.createButton();
|
|
817
320
|
}
|
|
818
321
|
|
|
819
322
|
// ═══ 3.5 语音按钮 ═══
|
|
@@ -1013,6 +516,10 @@ btn.addEventListener("click", function () {
|
|
|
1013
516
|
var toolbar = document.querySelector(".agent-chat__toolbar-left");
|
|
1014
517
|
if (!toolbar || document.querySelector("#myclaw-voice-btn")) return;
|
|
1015
518
|
|
|
519
|
+
if (window.myclawIteration) {
|
|
520
|
+
window.myclawIteration.init({ trySend: trySend });
|
|
521
|
+
}
|
|
522
|
+
|
|
1016
523
|
var voiceBtn = createVoiceButton();
|
|
1017
524
|
var promptBtn = createPromptButton();
|
|
1018
525
|
|
|
@@ -1380,8 +887,24 @@ btn.addEventListener("click", function () {
|
|
|
1380
887
|
var form = document.createElement("div");
|
|
1381
888
|
form.style.cssText = "padding: 16px 20px;display:flex;flex-direction:column;gap:10px;color:#cdd6f4;font-family:monospace;font-size:13px;";
|
|
1382
889
|
|
|
890
|
+
// 从 URL 解析当前页面的伙伴名
|
|
891
|
+
function getCurrentAgentName() {
|
|
892
|
+
var params = new URLSearchParams(window.location.search);
|
|
893
|
+
var session = params.get('session');
|
|
894
|
+
if (session) {
|
|
895
|
+
var decoded = decodeURIComponent(session);
|
|
896
|
+
if (decoded.indexOf('agent:') === 0) {
|
|
897
|
+
var parts = decoded.split(':');
|
|
898
|
+
if (parts.length >= 2) return parts[1];
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
var agent = params.get('agent');
|
|
902
|
+
if (agent) return agent;
|
|
903
|
+
return '';
|
|
904
|
+
}
|
|
905
|
+
|
|
1383
906
|
// 弹出 input 小弹框
|
|
1384
|
-
function promptAndRun(title, placeholder, hint, cmdTemplate, btnColor) {
|
|
907
|
+
function promptAndRun(title, placeholder, hint, cmdTemplate, btnColor, defaultValue) {
|
|
1385
908
|
var mask = document.createElement("div");
|
|
1386
909
|
mask.style.cssText = [
|
|
1387
910
|
"position:fixed",
|
|
@@ -1427,6 +950,7 @@ btn.addEventListener("click", function () {
|
|
|
1427
950
|
var input = document.createElement("input");
|
|
1428
951
|
input.type = "text";
|
|
1429
952
|
input.placeholder = placeholder;
|
|
953
|
+
input.value = defaultValue || '';
|
|
1430
954
|
input.style.cssText = "padding:8px 10px;background:#252536;border:1px solid #3d3d5c;border-radius:4px;color:#cdd6f4;font-size:13px;font-family:monospace;outline:none;";
|
|
1431
955
|
input.onfocus = function () { input.style.borderColor = btnColor; };
|
|
1432
956
|
input.onblur = function () { input.style.borderColor = "#3d3d5c"; };
|
|
@@ -1472,7 +996,7 @@ btn.addEventListener("click", function () {
|
|
|
1472
996
|
// ── 按钮列表 ──
|
|
1473
997
|
var btns = [
|
|
1474
998
|
{ label: "\uD83E\uDD1D \u65B0\u4F19\u4F34", desc: "\u521B\u5EFA\u4E00\u4E2A\u65B0\u7684 AI \u4F19\u4F34", hasInput: true, inputTitle: "\u65B0\u5EFA\u4F19\u4F34", placeholder: "\u8F93\u5165\u65B0\u4F19\u4F34\u540D\u79F0\uFF0C\u5982 my-cat", hint: "\u7ED9\u4F60\u7684\u65B0 AI \u4F19\u4F34\u8D77\u4E2A\u540D\u5B57\uFF08\u82F1\u6587\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u8FDE\u5B57\u7B26\uFF09\uFF0C\u70B9\u51FB\u540E\u4F1A\u81EA\u52A8\u521B\u5EFA", cmd: "mc new {name}", color: "#3b82f6" },
|
|
1475
|
-
{ label: "\uD83D\uDCAC \u6DFB\u52A0\u5BF9\u8BDD", desc: "\u6253\u5F00\u5DF2\u6709\u4F19\u4F34\u7684\u5BF9\u8BDD\u7A97\u53E3", hasInput: true, inputTitle: "\u6DFB\u52A0\u5BF9\u8BDD", placeholder: "\u8F93\u5165\u4F19\u4F34\u540D\u79F0\uFF0C\u5982 kakaxi", hint: "\u8F93\u5165\u4F60\u7684\u4F19\u4F34\u7684\u540D\u79F0\uFF08\u82F1\u6587\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u8FDE\u5B57\u7B26\uFF09\uFF0C\u70B9\u51FB\u540E\u4F1A\u6253\u5F00\u5BF9\u8BDD\u7A97\u53E3", cmd: "mc tui {name}", color: "#10b981" },
|
|
999
|
+
{ label: "\uD83D\uDCAC \u6DFB\u52A0\u5BF9\u8BDD", desc: "\u6253\u5F00\u5DF2\u6709\u4F19\u4F34\u7684\u5BF9\u8BDD\u7A97\u53E3", hasInput: true, inputTitle: "\u6DFB\u52A0\u5BF9\u8BDD", placeholder: "\u8F93\u5165\u4F19\u4F34\u540D\u79F0\uFF0C\u5982 kakaxi", hint: "\u8F93\u5165\u4F60\u7684\u4F19\u4F34\u7684\u540D\u79F0\uFF08\u82F1\u6587\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u8FDE\u5B57\u7B26\uFF09\uFF0C\u70B9\u51FB\u540E\u4F1A\u6253\u5F00\u5BF9\u8BDD\u7A97\u53E3", cmd: "mc tui {name}", color: "#10b981", getDefault: getCurrentAgentName },
|
|
1476
1000
|
{ label: "\uD83D\uDD04 \u91CD\u542F\u670D\u52A1", desc: "\u91CD\u542F\u6587\u4EF6\u670D\u52A1", hasInput: false, cmd: "mc server", color: "#ef4444" },
|
|
1477
1001
|
{ label: "\uD83E\uDD9E \u91CD\u542F\u9F99\u867E", desc: "\u91CD\u542F OpenClaw \u6838\u5FC3\u670D\u52A1", hasInput: false, cmd: "mc all", color: "#f59e0b" },
|
|
1478
1002
|
];
|
|
@@ -1520,7 +1044,7 @@ btn.addEventListener("click", function () {
|
|
|
1520
1044
|
|
|
1521
1045
|
row.onclick = function () {
|
|
1522
1046
|
if (item.hasInput) {
|
|
1523
|
-
promptAndRun(item.inputTitle, item.placeholder, item.hint, item.cmd, item.color);
|
|
1047
|
+
promptAndRun(item.inputTitle, item.placeholder, item.hint, item.cmd, item.color, item.getDefault ? item.getDefault() : '');
|
|
1524
1048
|
} else {
|
|
1525
1049
|
runCommand(item.cmd);
|
|
1526
1050
|
}
|