@aiyiran/myclaw 1.0.255 → 1.0.257

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.
@@ -193,6 +193,19 @@
193
193
  var headerRight = document.createElement('span');
194
194
  headerRight.style.cssText = 'display:flex;align-items:center;gap:10px;';
195
195
 
196
+ // 展示间跳转(发布按钮左边)
197
+ var showcaseLink = document.createElement('a');
198
+ var _scEnv = detectEnvironment();
199
+ var _scClaw = _scEnv.remote ? _scEnv.clawName : (lastKnownClawName || '');
200
+ var _scWs = getWorkspaceId();
201
+ showcaseLink.href = 'https://www.yiranlaoshi.com/showcase?claw=' + _scClaw + '&workspace=' + _scWs;
202
+ showcaseLink.target = '_blank';
203
+ showcaseLink.textContent = '\uD83D\uDC41 \u9879\u76EE\u96C6';
204
+ showcaseLink.style.cssText = 'cursor:pointer;padding:2px 10px;border-radius:3px;font-size:12px;background:rgba(255,255,255,0.08);transition:background 0.15s;color:#cdd6f4;text-decoration:none;';
205
+ showcaseLink.onmouseenter = function () { showcaseLink.style.background = 'rgba(255,255,255,0.18)'; };
206
+ showcaseLink.onmouseleave = function () { showcaseLink.style.background = 'rgba(255,255,255,0.08)'; };
207
+ headerRight.appendChild(showcaseLink);
208
+
196
209
  var publishBtn = document.createElement('span');
197
210
  publishBtn.textContent = '\u53D1\u5E03';
198
211
  publishBtn.style.cssText = 'cursor:pointer;padding:2px 10px;border-radius:3px;font-size:12px;background:rgba(255,255,255,0.08);transition:background 0.15s;';
@@ -224,8 +237,35 @@
224
237
 
225
238
  content.innerHTML = '<div style="text-align:center;padding:32px;color:#888;">加载中...</div>';
226
239
 
240
+ // Fork 按钮底部栏
241
+ var panelFooter = document.createElement('div');
242
+ panelFooter.style.cssText = [
243
+ 'padding: 8px 10px',
244
+ 'background: #252536',
245
+ 'border-top: 1px solid #3d3d5c',
246
+ 'flex-shrink: 0',
247
+ ].join(';');
248
+ var forkPanelBtn = document.createElement('div');
249
+ forkPanelBtn.textContent = '\uD83D\uDD00 fork\u4ED6\u4EBA\u4F5C\u54C1';
250
+ forkPanelBtn.style.cssText = [
251
+ 'cursor: pointer',
252
+ 'padding: 6px 10px',
253
+ 'border-radius: 4px',
254
+ 'font-size: 12px',
255
+ 'font-family: monospace',
256
+ 'color: #cdd6f4',
257
+ 'background: rgba(255,255,255,0.06)',
258
+ 'text-align: center',
259
+ 'transition: background 0.15s',
260
+ ].join(';');
261
+ forkPanelBtn.onmouseenter = function () { forkPanelBtn.style.background = 'rgba(255,255,255,0.14)'; };
262
+ forkPanelBtn.onmouseleave = function () { forkPanelBtn.style.background = 'rgba(255,255,255,0.06)'; };
263
+ forkPanelBtn.onclick = function () { openForkModal(); };
264
+ panelFooter.appendChild(forkPanelBtn);
265
+
227
266
  panel.appendChild(header);
228
267
  panel.appendChild(content);
268
+ panel.appendChild(panelFooter);
229
269
  document.body.appendChild(panel);
230
270
 
231
271
  // 立即拉一次,后续由轮询更新
@@ -418,6 +458,26 @@
418
458
  fname.appendChild(badge);
419
459
  }
420
460
 
461
+ // 复制相对路径按钮
462
+ var copyPathBtn = document.createElement('span');
463
+ copyPathBtn.textContent = '[复制]';
464
+ copyPathBtn.style.cssText = 'color:#6c6caa;font-size:10px;font-weight:bold;flex-shrink:0;cursor:pointer;transition:color 0.15s;';
465
+ copyPathBtn.onmouseenter = function () { copyPathBtn.style.color = '#a78bfa'; };
466
+ copyPathBtn.onmouseleave = function () { copyPathBtn.style.color = '#6c6caa'; };
467
+ copyPathBtn.onclick = function (e) {
468
+ e.stopPropagation();
469
+ var relativePath = getWorkspaceId() + '/' + (asset.path || '');
470
+ navigator.clipboard.writeText(relativePath).then(function () {
471
+ copyPathBtn.textContent = '[已复制]';
472
+ copyPathBtn.style.color = '#10b981';
473
+ setTimeout(function () {
474
+ copyPathBtn.textContent = '[复制]';
475
+ copyPathBtn.style.color = '#6c6caa';
476
+ }, 1500);
477
+ });
478
+ };
479
+ fname.appendChild(copyPathBtn);
480
+
421
481
  fname.appendChild(nameSpan);
422
482
 
423
483
  row.appendChild(time);
@@ -848,6 +908,16 @@
848
908
  'animation: myclaw-success-pop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1)',
849
909
  ].join(';');
850
910
 
911
+ // 右上角关闭按钮
912
+ var successCloseX = document.createElement('span');
913
+ successCloseX.textContent = '\u2715';
914
+ successCloseX.style.cssText = 'position:absolute;top:12px;right:14px;cursor:pointer;font-size:16px;color:#888;padding:4px 6px;border-radius:3px;transition:background 0.15s;z-index:1;';
915
+ successCloseX.onmouseenter = function () { successCloseX.style.background = 'rgba(255,255,255,0.1)'; successCloseX.style.color = '#cdd6f4'; };
916
+ successCloseX.onmouseleave = function () { successCloseX.style.background = 'none'; successCloseX.style.color = '#888'; };
917
+ successCloseX.onclick = function () { var m = document.querySelector('#myclaw-publish-success'); if (m) m.remove(); };
918
+ box.style.position = 'relative';
919
+ box.appendChild(successCloseX);
920
+
851
921
  // 头部:庆祝动画区
852
922
  var hero = document.createElement('div');
853
923
  hero.style.cssText = [
@@ -986,15 +1056,10 @@
986
1056
  var qrSection = document.createElement('div');
987
1057
  qrSection.style.cssText = 'display:flex;flex-direction:column;align-items:center;gap:6px;padding-top:4px;';
988
1058
 
989
- var qrCanvas = document.createElement('canvas');
990
- qrCanvas.style.cssText = 'width:140px;height:140px;border-radius:6px;';
991
- try {
992
- generateQR(qrCanvas, data.permanent_url, 280);
993
- } catch (e) {
994
- console.warn('[myclaw-artifacts] QR generate error:', e);
995
- qrCanvas.style.display = 'none';
996
- }
997
- qrSection.appendChild(qrCanvas);
1059
+ var qrDiv = document.createElement('div');
1060
+ qrDiv.style.cssText = 'width:140px;height:140px;border-radius:6px;overflow:hidden;background:#fff;display:flex;align-items:center;justify-content:center;';
1061
+ loadAndGenerateQR(qrDiv, data.permanent_url, 140);
1062
+ qrSection.appendChild(qrDiv);
998
1063
 
999
1064
  var qrHint = document.createElement('div');
1000
1065
  qrHint.style.cssText = 'font-size:11px;color:#888;font-family:monospace;';
@@ -1035,7 +1100,7 @@
1035
1100
  footer.appendChild(showcaseBtn);
1036
1101
 
1037
1102
  var closeSuccessBtn = document.createElement('button');
1038
- closeSuccessBtn.textContent = '\u5F00\u5FC3\uFF01';
1103
+ closeSuccessBtn.textContent = '\u6211\u8981\u518D\u6539\u6539\uFF01';
1039
1104
  closeSuccessBtn.style.cssText = [
1040
1105
  'padding: 10px 40px',
1041
1106
  'background: #4a4a7a',
@@ -1074,8 +1139,38 @@
1074
1139
  return row;
1075
1140
  }
1076
1141
 
1077
- // ═══ 轻量 QR 码生成(纯 JS,无依赖) ═══
1078
- // 基于 qrcode-generator (MIT) 的核心算法精简版
1142
+ // ═══ QR 码生成(qrcodejs,按需从 CDN 加载) ═══
1143
+ function loadAndGenerateQR(container, text, size) {
1144
+ function doGenerate() {
1145
+ try {
1146
+ new window.QRCode(container, {
1147
+ text: text,
1148
+ width: size,
1149
+ height: size,
1150
+ colorDark: '#000000',
1151
+ colorLight: '#ffffff',
1152
+ correctLevel: window.QRCode.CorrectLevel.M,
1153
+ });
1154
+ } catch (e) {
1155
+ console.warn('[myclaw-artifacts] QR generate error:', e);
1156
+ container.style.display = 'none';
1157
+ }
1158
+ }
1159
+ if (window.QRCode) {
1160
+ doGenerate();
1161
+ return;
1162
+ }
1163
+ var script = document.createElement('script');
1164
+ script.src = 'https://cdn.bootcdn.net/ajax/libs/qrcodejs/1.0.0/qrcode.min.js';
1165
+ script.onload = function () { doGenerate(); };
1166
+ script.onerror = function () {
1167
+ console.warn('[myclaw-artifacts] Failed to load qrcodejs');
1168
+ container.style.display = 'none';
1169
+ };
1170
+ document.head.appendChild(script);
1171
+ }
1172
+
1173
+ // 以下为废弃的旧版手写 QR 实现(已不使用,保留以备回滚)
1079
1174
  function generateQR(canvas, text, size) {
1080
1175
  // 使用 Google Charts API 的轻量替代:用 img 加载 QR 码
1081
1176
  // 但为了避免外部依赖,这里使用内嵌的极简 QR 生成
@@ -1437,6 +1532,179 @@
1437
1532
  if (modal) modal.remove();
1438
1533
  }
1439
1534
 
1535
+ // ═══ Fork 他人作品弹框 ═══
1536
+ function openForkModal() {
1537
+ if (document.querySelector('#myclaw-fork-modal')) return;
1538
+
1539
+ var overlay = document.createElement('div');
1540
+ overlay.id = 'myclaw-fork-modal';
1541
+ overlay.style.cssText = [
1542
+ 'position: fixed',
1543
+ 'top: 0',
1544
+ 'left: 0',
1545
+ 'width: 100vw',
1546
+ 'height: 100vh',
1547
+ 'background: rgba(0, 0, 0, 0.4)',
1548
+ 'z-index: 99999',
1549
+ 'display: flex',
1550
+ 'align-items: center',
1551
+ 'justify-content: center',
1552
+ 'animation: myclaw-fade-in 0.15s ease',
1553
+ ].join(';');
1554
+ overlay.onclick = function (e) { if (e.target === overlay) closeForkModal(); };
1555
+
1556
+ var box = document.createElement('div');
1557
+ box.style.cssText = [
1558
+ 'width: 480px',
1559
+ 'background: #1e1e2e',
1560
+ 'border-radius: 8px',
1561
+ 'overflow: hidden',
1562
+ 'display: flex',
1563
+ 'flex-direction: column',
1564
+ 'box-shadow: 0 8px 32px rgba(0,0,0,0.5)',
1565
+ ].join(';');
1566
+
1567
+ // 标题栏
1568
+ var forkHeader = document.createElement('div');
1569
+ forkHeader.style.cssText = [
1570
+ 'display: flex',
1571
+ 'align-items: center',
1572
+ 'justify-content: space-between',
1573
+ 'padding: 10px 14px',
1574
+ 'background: #2d2d3f',
1575
+ 'color: #cdd6f4',
1576
+ 'font-size: 13px',
1577
+ 'font-family: monospace',
1578
+ 'user-select: none',
1579
+ 'flex-shrink: 0',
1580
+ ].join(';');
1581
+ forkHeader.innerHTML = '<span>\uD83D\uDD00 Fork \u4ED6\u4EBA\u4F5C\u54C1</span>';
1582
+ var forkCloseBtn = document.createElement('span');
1583
+ forkCloseBtn.textContent = '\u2715';
1584
+ forkCloseBtn.style.cssText = 'cursor:pointer;padding:2px 6px;border-radius:3px;font-size:14px;transition:background 0.15s;';
1585
+ forkCloseBtn.onmouseenter = function () { forkCloseBtn.style.background = 'rgba(255,255,255,0.1)'; };
1586
+ forkCloseBtn.onmouseleave = function () { forkCloseBtn.style.background = 'none'; };
1587
+ forkCloseBtn.onclick = function () { closeForkModal(); };
1588
+ forkHeader.appendChild(forkCloseBtn);
1589
+
1590
+ // 表单
1591
+ var forkForm = document.createElement('div');
1592
+ forkForm.style.cssText = 'padding: 20px;display:flex;flex-direction:column;gap:10px;color:#cdd6f4;font-family:monospace;font-size:13px;';
1593
+
1594
+ var urlLabel = document.createElement('label');
1595
+ urlLabel.textContent = '\u4F5C\u54C1 URL';
1596
+ urlLabel.style.cssText = 'font-size:12px;color:#888;';
1597
+
1598
+ var urlInput = document.createElement('input');
1599
+ urlInput.type = 'text';
1600
+ urlInput.placeholder = 'https://cdn.yiranlaoshi.com/...';
1601
+ urlInput.style.cssText = [
1602
+ 'padding: 8px 10px',
1603
+ 'background: #252536',
1604
+ 'border: 1px solid #3d3d5c',
1605
+ 'border-radius: 4px',
1606
+ 'color: #cdd6f4',
1607
+ 'font-size: 13px',
1608
+ 'font-family: monospace',
1609
+ 'outline: none',
1610
+ ].join(';');
1611
+ urlInput.onfocus = function () { urlInput.style.borderColor = '#6c6caa'; };
1612
+ urlInput.onblur = function () { urlInput.style.borderColor = errVisible ? '#ff4444' : '#3d3d5c'; };
1613
+
1614
+ var errVisible = false;
1615
+ var errMsg = document.createElement('div');
1616
+ errMsg.style.cssText = 'font-size:12px;color:#ff4444;display:none;';
1617
+ errMsg.textContent = '\u8BF7\u8F93\u5165\u5B8C\u6574\u7684 URL\uFF08\u9700\u4EE5 http:// \u6216 https:// \u5F00\u5934\uFF09';
1618
+
1619
+ forkForm.appendChild(urlLabel);
1620
+ forkForm.appendChild(urlInput);
1621
+ forkForm.appendChild(errMsg);
1622
+
1623
+ // 确认按钮
1624
+ var forkSubmitBtn = document.createElement('button');
1625
+ forkSubmitBtn.textContent = '\u786E\u8BA4 Fork';
1626
+ forkSubmitBtn.style.cssText = [
1627
+ 'margin: 0 20px 20px',
1628
+ 'padding: 10px',
1629
+ 'background: #4a4a7a',
1630
+ 'border: none',
1631
+ 'border-radius: 4px',
1632
+ 'color: #cdd6f4',
1633
+ 'font-size: 13px',
1634
+ 'font-family: monospace',
1635
+ 'cursor: pointer',
1636
+ 'transition: background 0.15s',
1637
+ ].join(';');
1638
+ forkSubmitBtn.onmouseenter = function () { if (!forkSubmitBtn.disabled) forkSubmitBtn.style.background = '#5a5a9a'; };
1639
+ forkSubmitBtn.onmouseleave = function () { if (!forkSubmitBtn.disabled) forkSubmitBtn.style.background = '#4a4a7a'; };
1640
+
1641
+ forkSubmitBtn.onclick = function () {
1642
+ var url = urlInput.value.trim();
1643
+
1644
+ // 校验 URL 完整性
1645
+ var valid = false;
1646
+ try {
1647
+ var parsed = new URL(url);
1648
+ valid = parsed.protocol === 'http:' || parsed.protocol === 'https:';
1649
+ } catch (e) { valid = false; }
1650
+
1651
+ if (!valid) {
1652
+ urlInput.style.borderColor = '#ff4444';
1653
+ errMsg.style.display = 'block';
1654
+ errVisible = true;
1655
+ return;
1656
+ }
1657
+ urlInput.style.borderColor = '#3d3d5c';
1658
+ errMsg.style.display = 'none';
1659
+ errVisible = false;
1660
+
1661
+ forkSubmitBtn.disabled = true;
1662
+ forkSubmitBtn.textContent = '\u23F3 \u7B49\u5F85\u4E2D...';
1663
+ forkSubmitBtn.style.background = '#3a3a5a';
1664
+ forkSubmitBtn.style.cursor = 'default';
1665
+ urlInput.disabled = true;
1666
+
1667
+ fetch('https://claw.kekouen.cn/sync', {
1668
+ method: 'POST',
1669
+ headers: { 'Content-Type': 'application/json' },
1670
+ body: JSON.stringify({ url: url }),
1671
+ })
1672
+ .then(function (res) {
1673
+ if (!res.ok) throw new Error('HTTP ' + res.status);
1674
+ return res.json();
1675
+ })
1676
+ .then(function () {
1677
+ forkSubmitBtn.textContent = '\u2705 Fork \u6210\u529F\uFF01';
1678
+ forkSubmitBtn.style.background = '#10b981';
1679
+ setTimeout(function () { closeForkModal(); }, 2000);
1680
+ })
1681
+ .catch(function (err) {
1682
+ console.error('[myclaw-fork]', err);
1683
+ forkSubmitBtn.disabled = false;
1684
+ urlInput.disabled = false;
1685
+ forkSubmitBtn.textContent = '\u274C \u8BF7\u6C42\u5931\u8D25\uFF0C\u70B9\u51FB\u91CD\u8BD5';
1686
+ forkSubmitBtn.style.background = '#7a2a2a';
1687
+ forkSubmitBtn.style.cursor = 'pointer';
1688
+ setTimeout(function () {
1689
+ forkSubmitBtn.textContent = '\u786E\u8BA4 Fork';
1690
+ forkSubmitBtn.style.background = '#4a4a7a';
1691
+ }, 2500);
1692
+ });
1693
+ };
1694
+
1695
+ box.appendChild(forkHeader);
1696
+ box.appendChild(forkForm);
1697
+ box.appendChild(forkSubmitBtn);
1698
+ overlay.appendChild(box);
1699
+ document.body.appendChild(overlay);
1700
+ urlInput.focus();
1701
+ }
1702
+
1703
+ function closeForkModal() {
1704
+ var modal = document.querySelector('#myclaw-fork-modal');
1705
+ if (modal) modal.remove();
1706
+ }
1707
+
1440
1708
  // ═══ 注入样式 ═══
1441
1709
  function injectStyles() {
1442
1710
  if (document.querySelector('#myclaw-artifacts-styles')) return;
package/index.js CHANGED
@@ -334,6 +334,10 @@ function runNew() {
334
334
  console.log(colors.dim + '如果唤醒失败,可手动发送命令:' + NC);
335
335
  console.log(' ' + Y + 'openclaw agent --agent ' + agentId + ' --message "你好"' + NC);
336
336
  console.log('');
337
+
338
+ // 在桌面创建/覆盖浏览器快捷图标
339
+ createDesktopShortcut('http://127.0.0.1:18789?token=' + TOKEN);
340
+
337
341
  process.exit(0);
338
342
  }
339
343
  }
@@ -813,6 +817,50 @@ function runOpen() {
813
817
  console.log('');
814
818
  }
815
819
 
820
+ // ============================================================================
821
+ // 桌面快捷方式(浏览器入口图标)
822
+ // ============================================================================
823
+
824
+ function createDesktopShortcut(url) {
825
+ const fs = require('fs');
826
+ const platform = os.platform();
827
+ const desktopPath = path.join(os.homedir(), 'Desktop');
828
+
829
+ if (!fs.existsSync(desktopPath)) {
830
+ console.log('[shortcut] ⚠ 未找到桌面目录,跳过');
831
+ return;
832
+ }
833
+
834
+ if (platform === 'darwin') {
835
+ // macOS: .webloc 文件,双击用默认浏览器打开
836
+ const webloc = path.join(desktopPath, 'OpenClaw.webloc');
837
+ const content = `<?xml version="1.0" encoding="UTF-8"?>
838
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
839
+ <plist version="1.0">
840
+ <dict>
841
+ <key>URL</key>
842
+ <string>${url}</string>
843
+ </dict>
844
+ </plist>`;
845
+ fs.writeFileSync(webloc, content, 'utf8');
846
+ console.log('[shortcut] ✅ 桌面快捷方式已更新: OpenClaw.webloc');
847
+ } else if (platform === 'linux') {
848
+ // Linux / WSL: .desktop 文件
849
+ const desktop = path.join(desktopPath, 'OpenClaw.desktop');
850
+ const content = `[Desktop Entry]
851
+ Type=Link
852
+ Name=OpenClaw
853
+ URL=${url}
854
+ Icon=text-html
855
+ `;
856
+ fs.writeFileSync(desktop, content, 'utf8');
857
+ try { execSync('chmod +x "' + desktop + '"', { stdio: 'pipe' }); } catch {}
858
+ console.log('[shortcut] ✅ 桌面快捷方式已更新: OpenClaw.desktop');
859
+ } else {
860
+ console.log('[shortcut] ⚠ Windows 请使用 mc bat 创建桌面快捷方式');
861
+ }
862
+ }
863
+
816
864
  // ============================================================================
817
865
  // Patch / Unpatch / Restart
818
866
  // ============================================================================
@@ -1215,7 +1263,9 @@ function showMachineMenu() {
1215
1263
  console.log(colors.green + ' → 已选择: ' + selected.name + ' (' + selected.claw + ')' + colors.nc);
1216
1264
  console.log(' ' + colors.dim + '→ 正在用 Chrome 打开...' + colors.nc);
1217
1265
  const { execSync } = require('child_process');
1218
- execSync('open -a "Google Chrome" "https://' + selected.claw + '.kekouen.cn?token=aiyiran"', { stdio: 'ignore' });
1266
+ const machineUrl = 'https://' + selected.claw + '.kekouen.cn?token=aiyiran';
1267
+ execSync('open -a "Google Chrome" "' + machineUrl + '"', { stdio: 'ignore' });
1268
+ createDesktopShortcut(machineUrl);
1219
1269
  } else {
1220
1270
  console.log('[' + colors.red + '错误' + colors.nc + '] 无效选择');
1221
1271
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiyiran/myclaw",
3
- "version": "1.0.255",
3
+ "version": "1.0.257",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {