@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.
- package/assets/openclaw.ico +0 -0
- package/index.js +9 -3
- package/lobster-icon-generator.html +75 -3
- package/package.json +1 -1
package/assets/openclaw.ico
CHANGED
|
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
|
|
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 到最新版本
|
|
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'
|
|
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
|
-
<
|
|
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
|
-
|
|
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>
|