@aiyiran/myclaw 1.0.85 → 1.0.87

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.
Binary file
package/index.js CHANGED
@@ -365,7 +365,7 @@ REM Gateway not running -> update, launch in new window, refresh self
365
365
  echo Starting...
366
366
  echo.
367
367
  echo [update] Windows...
368
- call myclaw up
368
+ call myclaw update
369
369
  echo.
370
370
  echo [launch] Starting Gateway...
371
371
  start "OpenClaw Gateway" wsl -d OpenClaw -- myclaw launch
@@ -790,7 +790,8 @@ function showHelp() {
790
790
  console.log(' install 安装 OpenClaw 服务');
791
791
  console.log(' status 简化版状态查看(学生友好)');
792
792
  console.log(' new 创建新的 Agent(学生练习用)');
793
- console.log(' update 自动升级 MyClaw 到最新版本 (别名: up)');
793
+ console.log(' update 自动升级 MyClaw 到最新版本');
794
+ console.log(' up 升级 + 刷新桌面快捷方式 (= update + bat)');
794
795
  console.log(' open 打开浏览器控制台(自动带 token)');
795
796
  console.log(' wsl2 WSL2 一键安装/修复 (仅限 Windows)');
796
797
  console.log(' bat 在桌面生成一键启动脚本 (仅限 Windows)');
@@ -836,8 +837,13 @@ if (!command || command === 'help' || command === '--help' || command === '-h')
836
837
  runStatus();
837
838
  } else if (command === 'new') {
838
839
  runNew();
839
- } else if (command === 'update' || command === 'up') {
840
+ } else if (command === 'update') {
840
841
  runUpdate();
842
+ } else if (command === 'up') {
843
+ runUpdate();
844
+ if (detectPlatform() === 'windows') {
845
+ runBat();
846
+ }
841
847
  } else if (command === 'open') {
842
848
  runOpen();
843
849
  } else if (command === 'wsl2') {
@@ -91,10 +91,12 @@
91
91
  <!-- 画布分辨率提升,渲染战斗姿态和旋转 -->
92
92
  <canvas id="iconCanvas" width="256" height="256"></canvas>
93
93
  <br>
94
- <button onclick="downloadIcon()">⬇️ 下载为 PNG 格式</button>
94
+ <div style="display: flex; gap: 12px; justify-content: center; flex-wrap: wrap;">
95
+ <button onclick="downloadIcon()">⬇️ 下载为 PNG 格式</button>
96
+ <button onclick="downloadICO()" style="background: linear-gradient(135deg, #06b6d4 0%, #0891b2 100%); box-shadow: 0 0 15px rgba(6, 182, 212, 0.4);">⬇️ 下载为 ICO 格式</button>
97
+ </div>
95
98
  <div class="desc">
96
- 右键保存或点击下载。<br>
97
- 你可以用第三方工具把下载的 PNG 转换为 .ico 文件。
99
+ PNG 为原始图片,ICO 包含 16/32/48/256 四种尺寸,可直接用于桌面图标。
98
100
  </div>
99
101
  </div>
100
102
  </div>
@@ -228,6 +230,76 @@
228
230
  link.href = dataURL;
229
231
  link.click();
230
232
  }
233
+
234
+ // ====== ICO 生成逻辑 ======
235
+ // 将 Canvas 缩放到指定尺寸并返回 PNG 的 Uint8Array
236
+ function canvasToPngBytes(srcCanvas, targetSize) {
237
+ const tmp = document.createElement('canvas');
238
+ tmp.width = targetSize;
239
+ tmp.height = targetSize;
240
+ const tctx = tmp.getContext('2d');
241
+ // 对小尺寸禁用平滑,保持像素锐利
242
+ tctx.imageSmoothingEnabled = (targetSize > 48);
243
+ tctx.drawImage(srcCanvas, 0, 0, targetSize, targetSize);
244
+ const dataURL = tmp.toDataURL('image/png');
245
+ const base64 = dataURL.split(',')[1];
246
+ const binary = atob(base64);
247
+ const bytes = new Uint8Array(binary.length);
248
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
249
+ return bytes;
250
+ }
251
+
252
+ function buildICO(pngArrays, sizes) {
253
+ // ICO 文件结构:
254
+ // ICONDIR (6 bytes) + N x ICONDIRENTRY (16 bytes each) + N x PNG data
255
+ const numImages = pngArrays.length;
256
+ const headerSize = 6 + numImages * 16;
257
+ let totalSize = headerSize;
258
+ for (const png of pngArrays) totalSize += png.length;
259
+
260
+ const buffer = new ArrayBuffer(totalSize);
261
+ const view = new DataView(buffer);
262
+
263
+ // ICONDIR header
264
+ view.setUint16(0, 0, true); // reserved
265
+ view.setUint16(2, 1, true); // type: 1 = ICO
266
+ view.setUint16(4, numImages, true); // image count
267
+
268
+ let dataOffset = headerSize;
269
+ for (let i = 0; i < numImages; i++) {
270
+ const entryOffset = 6 + i * 16;
271
+ const s = sizes[i];
272
+ const pngData = pngArrays[i];
273
+
274
+ view.setUint8(entryOffset + 0, s >= 256 ? 0 : s); // width (0 = 256)
275
+ view.setUint8(entryOffset + 1, s >= 256 ? 0 : s); // height
276
+ view.setUint8(entryOffset + 2, 0); // color palette count
277
+ view.setUint8(entryOffset + 3, 0); // reserved
278
+ view.setUint16(entryOffset + 4, 1, true); // color planes
279
+ view.setUint16(entryOffset + 6, 32, true); // bits per pixel
280
+ view.setUint32(entryOffset + 8, pngData.length, true); // data size
281
+ view.setUint32(entryOffset + 12, dataOffset, true); // data offset
282
+
283
+ // 写入 PNG 数据
284
+ const dst = new Uint8Array(buffer, dataOffset, pngData.length);
285
+ dst.set(pngData);
286
+ dataOffset += pngData.length;
287
+ }
288
+
289
+ return new Blob([buffer], { type: 'image/x-icon' });
290
+ }
291
+
292
+ function downloadICO() {
293
+ const sizes = [16, 32, 48, 256];
294
+ const pngArrays = sizes.map(s => canvasToPngBytes(canvas, s));
295
+ const blob = buildICO(pngArrays, sizes);
296
+ const url = URL.createObjectURL(blob);
297
+ const link = document.createElement('a');
298
+ link.download = 'openclaw-tech-lobster.ico';
299
+ link.href = url;
300
+ link.click();
301
+ URL.revokeObjectURL(url);
302
+ }
231
303
  </script>
232
304
  </body>
233
305
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiyiran/myclaw",
3
- "version": "1.0.85",
3
+ "version": "1.0.87",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {