@aiyiran/myclaw 1.1.19 → 1.1.21
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/settings.local.json +17 -1
- package/assets/myclaw-artifacts.js +145 -48
- package/index.js +36 -4
- package/package.json +1 -1
- package/server/artifacts_schema.py +32 -0
- package/server/fork.py +615 -0
- package/server/install-linux-guard.sh +88 -0
- package/server/myclaw-guard.sh +121 -0
- package/server/myclaw-sync.service +18 -0
- package/server/sync_workspace.py +398 -83
- package/skills/yiran-skill-media/scripts/registry.py +10 -14
|
@@ -5,7 +5,23 @@
|
|
|
5
5
|
"Bash(python3 -c \"import json,sys; d=json.load\\(sys.stdin\\); agents=d.get\\('agents',{}\\).get\\('list',[]\\); [print\\(a.get\\('id'\\), '|', a.get\\('workspace',''\\)\\) for a in agents if a]\")",
|
|
6
6
|
"Bash(node *)",
|
|
7
7
|
"Bash(curl -s \"https://cdn.bootcdn.net/ajax/libs/qrcodejs/1.0.0/qrcode.min.js\" -o /Users/yiran/.openclaw/workspace-yiranclaw/myclaw/assets/qrcode.min.js)",
|
|
8
|
-
"Bash(python3 *)"
|
|
8
|
+
"Bash(python3 *)",
|
|
9
|
+
"Bash(crontab -l)",
|
|
10
|
+
"Bash(launchctl list *)",
|
|
11
|
+
"Bash(claude config *)",
|
|
12
|
+
"Bash(defaults read *)",
|
|
13
|
+
"Bash(chmod +x *)",
|
|
14
|
+
"Bash(/usr/local/bin/claude config *)",
|
|
15
|
+
"Bash(claude --version)",
|
|
16
|
+
"Bash(mc --version)",
|
|
17
|
+
"Bash(mc server *)",
|
|
18
|
+
"Bash(kill %1)",
|
|
19
|
+
"Bash(wait)",
|
|
20
|
+
"Bash(CLAW_NAME=yiran timeout 6 python3 server/sync_workspace.py)",
|
|
21
|
+
"Bash(curl -s http://127.0.0.1:18800/api/artifacts?workspace=workspace)",
|
|
22
|
+
"Bash(curl *)",
|
|
23
|
+
"Bash(find /Users/yiran/.openclaw/workspace/ -not -path '*/.git/*' -not -path '*/.myclaw/*' -not -path '*/node_modules/*' -not -path '*/__pycache__/*' -type f -exec du -ch {} +)",
|
|
24
|
+
"Bash(find *)"
|
|
9
25
|
]
|
|
10
26
|
}
|
|
11
27
|
}
|
|
@@ -95,15 +95,19 @@
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
// ═══ 构建预览 URL ═══
|
|
98
|
-
// 统一走 CDN,clawName
|
|
98
|
+
// 统一走 CDN,clawName 只从两个可信来源取:
|
|
99
|
+
// 远程 → hostname 派生(detectEnvironment)
|
|
100
|
+
// 本地 → resolveClawName() 缓存的 lastKnownClawName
|
|
99
101
|
function buildPreviewUrl(data, assetPath) {
|
|
100
102
|
var env = detectEnvironment();
|
|
101
|
-
var clawName = env.remote ? env.clawName : lastKnownClawName;
|
|
102
103
|
var wsPrefix = getWorkspaceId();
|
|
103
|
-
|
|
104
|
+
var clawName = env.remote ? env.clawName : lastKnownClawName;
|
|
105
|
+
|
|
106
|
+
if (!clawName) {
|
|
104
107
|
console.error('[myclaw-artifacts] ❌ clawName 未就绪,无法构建预览链接');
|
|
105
108
|
return null;
|
|
106
109
|
}
|
|
110
|
+
|
|
107
111
|
return 'https://cdn.yiranlaoshi.com/' + clawName + '/' + wsPrefix + '/' + assetPath;
|
|
108
112
|
}
|
|
109
113
|
|
|
@@ -193,6 +197,42 @@
|
|
|
193
197
|
var headerRight = document.createElement('span');
|
|
194
198
|
headerRight.style.cssText = 'display:flex;align-items:center;gap:10px;';
|
|
195
199
|
|
|
200
|
+
// 刷新按钮(全量同步)
|
|
201
|
+
var resyncBtn = document.createElement('span');
|
|
202
|
+
resyncBtn.textContent = '\uD83D\uDD04';
|
|
203
|
+
resyncBtn.title = '\u5237\u65B0\u540C\u6B65';
|
|
204
|
+
resyncBtn.style.cssText = 'cursor:pointer;padding:2px 6px;border-radius:3px;font-size:13px;transition:all 0.15s;';
|
|
205
|
+
resyncBtn.onmouseenter = function () { resyncBtn.style.background = 'rgba(255,255,255,0.1)'; };
|
|
206
|
+
resyncBtn.onmouseleave = function () { if (!resyncBtn._syncing) resyncBtn.style.background = 'none'; };
|
|
207
|
+
resyncBtn.onclick = function () {
|
|
208
|
+
if (resyncBtn._syncing) return;
|
|
209
|
+
resyncBtn._syncing = true;
|
|
210
|
+
resyncBtn.style.animation = 'myclaw-spin 1s linear infinite';
|
|
211
|
+
resyncBtn.style.background = 'rgba(255,255,255,0.1)';
|
|
212
|
+
|
|
213
|
+
var wsPrefix = getWorkspaceId();
|
|
214
|
+
fetch(MYCLAW_API_BASE + '/api/resync?workspace=' + encodeURIComponent(wsPrefix), { method: 'POST' })
|
|
215
|
+
.then(function (res) { return res.json(); })
|
|
216
|
+
.then(function (data) {
|
|
217
|
+
if (data.ok) {
|
|
218
|
+
console.log('[myclaw-artifacts] \u2705 \u540C\u6B65\u5B8C\u6210');
|
|
219
|
+
var contentEl = document.querySelector('#myclaw-artifacts-content');
|
|
220
|
+
if (contentEl) fetchArtifacts(contentEl);
|
|
221
|
+
} else {
|
|
222
|
+
console.error('[myclaw-artifacts] \u274C \u540C\u6B65\u5931\u8D25:', data.error);
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
.catch(function (err) {
|
|
226
|
+
console.error('[myclaw-artifacts] \u274C \u540C\u6B65\u8BF7\u6C42\u5931\u8D25:', err.message);
|
|
227
|
+
})
|
|
228
|
+
.then(function () {
|
|
229
|
+
resyncBtn._syncing = false;
|
|
230
|
+
resyncBtn.style.animation = '';
|
|
231
|
+
resyncBtn.style.background = 'none';
|
|
232
|
+
});
|
|
233
|
+
};
|
|
234
|
+
headerRight.appendChild(resyncBtn);
|
|
235
|
+
|
|
196
236
|
// 展示间跳转(发布按钮左边)
|
|
197
237
|
var showcaseLink = document.createElement('a');
|
|
198
238
|
var _scEnv = detectEnvironment();
|
|
@@ -289,49 +329,40 @@
|
|
|
289
329
|
}
|
|
290
330
|
|
|
291
331
|
function fetchArtifactsFromLocalAPI(wsPrefix) {
|
|
292
|
-
|
|
332
|
+
var url = MYCLAW_API_BASE + '/api/artifacts?workspace=' + encodeURIComponent(wsPrefix);
|
|
333
|
+
console.log('[myclaw-artifacts] [1/3] 尝试 LocalAPI:', url);
|
|
334
|
+
return fetch(url)
|
|
293
335
|
.then(function (res) {
|
|
294
336
|
if (!res.ok) throw new Error('HTTP ' + res.status);
|
|
295
337
|
return res.json();
|
|
338
|
+
})
|
|
339
|
+
.then(function (data) {
|
|
340
|
+
console.log('[myclaw-artifacts] ✅ LocalAPI 成功,assets:', (data.assets || []).length);
|
|
341
|
+
return data;
|
|
296
342
|
});
|
|
297
343
|
}
|
|
298
344
|
|
|
299
|
-
function fetchArtifactsFromCDN(wsPrefix, clawName) {
|
|
300
|
-
if (!clawName) return Promise.reject(new Error('no claw name'));
|
|
301
|
-
var url = 'https://cdn.yiranlaoshi.com/' + clawName + '/' + wsPrefix + '/.myclaw/__MY_ARTIFACTS__.json?t=' + Date.now();
|
|
302
|
-
return fetch(url).then(function (res) {
|
|
303
|
-
if (!res.ok) throw new Error('HTTP ' + res.status);
|
|
304
|
-
return res.text();
|
|
305
|
-
}).then(function (text) {
|
|
306
|
-
if (text.trim().indexOf('<') === 0) throw new Error('Not JSON');
|
|
307
|
-
return JSON.parse(text);
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
|
|
311
345
|
function fetchArtifactsFromServerAPI(wsPrefix) {
|
|
312
346
|
var url = window.location.origin + '/cmd/api/preview?path=' + encodeURIComponent(wsPrefix + '/.myclaw/__MY_ARTIFACTS__.json');
|
|
347
|
+
console.log('[myclaw-artifacts] [2/2] 尝试 ServerAPI:', url);
|
|
313
348
|
return fetch(url).then(function (res) {
|
|
314
349
|
if (!res.ok) throw new Error('HTTP ' + res.status);
|
|
315
350
|
return res.json();
|
|
351
|
+
}).then(function (data) {
|
|
352
|
+
console.log('[myclaw-artifacts] ✅ ServerAPI 成功');
|
|
353
|
+
return data;
|
|
316
354
|
});
|
|
317
355
|
}
|
|
318
356
|
|
|
319
357
|
function fetchArtifacts(contentEl) {
|
|
320
|
-
var env = detectEnvironment();
|
|
321
358
|
var wsPrefix = getWorkspaceId();
|
|
322
|
-
var fetcher;
|
|
323
359
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
return fetchArtifactsFromCDN(wsPrefix, clawName);
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
fetcher
|
|
360
|
+
// LocalAPI → ServerAPI(两层降级,不走 CDN)
|
|
361
|
+
fetchArtifactsFromLocalAPI(wsPrefix)
|
|
362
|
+
.catch(function (err) {
|
|
363
|
+
console.warn('[myclaw-artifacts] ❌ LocalAPI 失败:', err.message, '→ 降级 ServerAPI');
|
|
364
|
+
return fetchArtifactsFromServerAPI(wsPrefix);
|
|
365
|
+
})
|
|
335
366
|
.then(function (data) {
|
|
336
367
|
cachedData = data;
|
|
337
368
|
if (!contentEl) return;
|
|
@@ -341,7 +372,8 @@
|
|
|
341
372
|
}
|
|
342
373
|
renderArtifactsList(contentEl, data);
|
|
343
374
|
})
|
|
344
|
-
.catch(function () {
|
|
375
|
+
.catch(function (err) {
|
|
376
|
+
console.error('[myclaw-artifacts] ❌ 全部失败:', err.message);
|
|
345
377
|
if (contentEl) {
|
|
346
378
|
contentEl.innerHTML = '<div style="text-align:center;padding:32px;color:#888;">暂无作品</div>';
|
|
347
379
|
}
|
|
@@ -511,6 +543,22 @@
|
|
|
511
543
|
if (document.querySelector('#myclaw-artifacts-preview')) return;
|
|
512
544
|
|
|
513
545
|
var previewUrl = buildPreviewUrl(data, asset.path);
|
|
546
|
+
if (!previewUrl) {
|
|
547
|
+
console.log('[myclaw-artifacts] ↻ clawName 未就绪,尝试重新获取一次...');
|
|
548
|
+
resolveClawName()
|
|
549
|
+
.then(function () {
|
|
550
|
+
var retriedPreviewUrl = buildPreviewUrl(data, asset.path);
|
|
551
|
+
if (!retriedPreviewUrl) {
|
|
552
|
+
console.error('[myclaw-artifacts] ❌ clawName 重试获取后仍未就绪,无法打开预览');
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
openPreviewModal(data, asset);
|
|
556
|
+
})
|
|
557
|
+
.catch(function (err) {
|
|
558
|
+
console.error('[myclaw-artifacts] ❌ clawName 重试获取失败:', err && err.message ? err.message : err);
|
|
559
|
+
});
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
514
562
|
|
|
515
563
|
var overlay = document.createElement('div');
|
|
516
564
|
overlay.id = 'myclaw-artifacts-preview';
|
|
@@ -556,8 +604,9 @@
|
|
|
556
604
|
openBtn.onmouseenter = function () { openBtn.style.background = 'rgba(255,255,255,0.18)'; };
|
|
557
605
|
openBtn.onmouseleave = function () { openBtn.style.background = 'rgba(255,255,255,0.08)'; };
|
|
558
606
|
openBtn.onclick = function () {
|
|
559
|
-
|
|
560
|
-
|
|
607
|
+
var urlWithTs = previewUrl + '?t=' + Date.now();
|
|
608
|
+
window.open(urlWithTs, '_blank');
|
|
609
|
+
navigator.clipboard.writeText(urlWithTs).then(function () {
|
|
561
610
|
openBtn.textContent = '\u2713 \u5DF2\u590D\u5236';
|
|
562
611
|
setTimeout(function () { openBtn.textContent = '\u5728\u65B0\u9875\u9762\u6253\u5F00'; }, 1500);
|
|
563
612
|
});
|
|
@@ -1177,6 +1226,35 @@
|
|
|
1177
1226
|
if (modal) modal.remove();
|
|
1178
1227
|
}
|
|
1179
1228
|
|
|
1229
|
+
// ═══ Fork 辅助函数 ═══
|
|
1230
|
+
function onForkError(err, btn, input) {
|
|
1231
|
+
console.error('[myclaw-fork]', err);
|
|
1232
|
+
btn.disabled = false;
|
|
1233
|
+
input.disabled = false;
|
|
1234
|
+
btn.textContent = '\u274C 失败,点击重试';
|
|
1235
|
+
btn.style.background = '#7a2a2a';
|
|
1236
|
+
btn.style.cursor = 'pointer';
|
|
1237
|
+
setTimeout(function () {
|
|
1238
|
+
btn.textContent = '\u786E\u8BA4 Fork';
|
|
1239
|
+
btn.style.background = '#4a4a7a';
|
|
1240
|
+
}, 2500);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
function showForkDoneToast(workspace, files) {
|
|
1244
|
+
var toast = document.createElement('div');
|
|
1245
|
+
toast.style.cssText = [
|
|
1246
|
+
'position:fixed', 'bottom:32px', 'right:24px', 'z-index:999999',
|
|
1247
|
+
'background:#10b981', 'color:#fff', 'padding:14px 20px',
|
|
1248
|
+
'border-radius:8px', 'font-family:monospace', 'font-size:13px',
|
|
1249
|
+
'box-shadow:0 4px 16px rgba(0,0,0,0.3)',
|
|
1250
|
+
'animation:myclaw-slide-in-right 0.25s ease',
|
|
1251
|
+
].join(';');
|
|
1252
|
+
toast.innerHTML = '\u2705 Fork 完成!<br>'
|
|
1253
|
+
+ '<span style="opacity:0.85;font-size:11px;">' + workspace + '(' + files + ' 个文件)</span>';
|
|
1254
|
+
document.body.appendChild(toast);
|
|
1255
|
+
setTimeout(function () { toast.remove(); }, 4000);
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1180
1258
|
// ═══ Fork 他人作品弹框 ═══
|
|
1181
1259
|
function openForkModal() {
|
|
1182
1260
|
if (document.querySelector('#myclaw-fork-modal')) return;
|
|
@@ -1304,12 +1382,12 @@
|
|
|
1304
1382
|
errVisible = false;
|
|
1305
1383
|
|
|
1306
1384
|
forkSubmitBtn.disabled = true;
|
|
1307
|
-
forkSubmitBtn.textContent = '\u23F3
|
|
1385
|
+
forkSubmitBtn.textContent = '\u23F3 Fork 中...';
|
|
1308
1386
|
forkSubmitBtn.style.background = '#3a3a5a';
|
|
1309
1387
|
forkSubmitBtn.style.cursor = 'default';
|
|
1310
1388
|
urlInput.disabled = true;
|
|
1311
1389
|
|
|
1312
|
-
fetch('
|
|
1390
|
+
fetch(MYCLAW_API_BASE + '/api/fork', {
|
|
1313
1391
|
method: 'POST',
|
|
1314
1392
|
headers: { 'Content-Type': 'application/json' },
|
|
1315
1393
|
body: JSON.stringify({ url: url }),
|
|
@@ -1318,22 +1396,35 @@
|
|
|
1318
1396
|
if (!res.ok) throw new Error('HTTP ' + res.status);
|
|
1319
1397
|
return res.json();
|
|
1320
1398
|
})
|
|
1321
|
-
.then(function () {
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1399
|
+
.then(function (data) {
|
|
1400
|
+
if (!data.job_id) throw new Error(data.error || 'no job_id');
|
|
1401
|
+
// 轮询 job 状态
|
|
1402
|
+
var jobId = data.job_id;
|
|
1403
|
+
var timer = setInterval(function () {
|
|
1404
|
+
fetch(MYCLAW_API_BASE + '/api/fork/status?job_id=' + encodeURIComponent(jobId))
|
|
1405
|
+
.then(function (r) { return r.json(); })
|
|
1406
|
+
.then(function (job) {
|
|
1407
|
+
if (job.status === 'running') return;
|
|
1408
|
+
clearInterval(timer);
|
|
1409
|
+
if (job.status === 'done') {
|
|
1410
|
+
forkSubmitBtn.textContent = '\u2705 Fork 成功!';
|
|
1411
|
+
forkSubmitBtn.style.background = '#10b981';
|
|
1412
|
+
setTimeout(function () {
|
|
1413
|
+
closeForkModal();
|
|
1414
|
+
showForkDoneToast(job.workspace, job.files);
|
|
1415
|
+
}, 800);
|
|
1416
|
+
} else {
|
|
1417
|
+
throw new Error(job.error || 'failed');
|
|
1418
|
+
}
|
|
1419
|
+
})
|
|
1420
|
+
.catch(function (err) {
|
|
1421
|
+
clearInterval(timer);
|
|
1422
|
+
onForkError(err, forkSubmitBtn, urlInput);
|
|
1423
|
+
});
|
|
1424
|
+
}, 1500);
|
|
1325
1425
|
})
|
|
1326
1426
|
.catch(function (err) {
|
|
1327
|
-
|
|
1328
|
-
forkSubmitBtn.disabled = false;
|
|
1329
|
-
urlInput.disabled = false;
|
|
1330
|
-
forkSubmitBtn.textContent = '\u274C \u8BF7\u6C42\u5931\u8D25\uFF0C\u70B9\u51FB\u91CD\u8BD5';
|
|
1331
|
-
forkSubmitBtn.style.background = '#7a2a2a';
|
|
1332
|
-
forkSubmitBtn.style.cursor = 'pointer';
|
|
1333
|
-
setTimeout(function () {
|
|
1334
|
-
forkSubmitBtn.textContent = '\u786E\u8BA4 Fork';
|
|
1335
|
-
forkSubmitBtn.style.background = '#4a4a7a';
|
|
1336
|
-
}, 2500);
|
|
1427
|
+
onForkError(err, forkSubmitBtn, urlInput);
|
|
1337
1428
|
});
|
|
1338
1429
|
};
|
|
1339
1430
|
|
|
@@ -1368,6 +1459,10 @@
|
|
|
1368
1459
|
' from { transform: scale(0.7); opacity: 0; }',
|
|
1369
1460
|
' to { transform: scale(1); opacity: 1; }',
|
|
1370
1461
|
'}',
|
|
1462
|
+
'@keyframes myclaw-spin {',
|
|
1463
|
+
' from { transform: rotate(0deg); }',
|
|
1464
|
+
' to { transform: rotate(360deg); }',
|
|
1465
|
+
'}',
|
|
1371
1466
|
].join('\n');
|
|
1372
1467
|
document.head.appendChild(style);
|
|
1373
1468
|
}
|
|
@@ -1376,6 +1471,8 @@
|
|
|
1376
1471
|
function init() {
|
|
1377
1472
|
injectStyles();
|
|
1378
1473
|
createArtifactsButton();
|
|
1474
|
+
// 本地环境:启动时获取一次 clawName 并缓存,轮询期间复用
|
|
1475
|
+
resolveClawName();
|
|
1379
1476
|
startPolling();
|
|
1380
1477
|
var env = detectEnvironment();
|
|
1381
1478
|
console.log('[myclaw-artifacts] ✅ 初始化完成 (' + (env.remote ? '远程: ' + env.clawName : '本地') + ')');
|
package/index.js
CHANGED
|
@@ -301,9 +301,12 @@ function runNew() {
|
|
|
301
301
|
const NC = colors.nc;
|
|
302
302
|
|
|
303
303
|
// 支持两种调用:
|
|
304
|
-
// mc new
|
|
305
|
-
// mc new <name>
|
|
304
|
+
// mc new → 交互输入名字
|
|
305
|
+
// mc new <name> → 直接使用传入的名字
|
|
306
|
+
// mc new <name> --first-message "..." → 自定义首条消息
|
|
306
307
|
const rawName = args[1];
|
|
308
|
+
const firstMessageIdx = args.indexOf('--first-message');
|
|
309
|
+
const customFirstMessage = firstMessageIdx !== -1 ? args[firstMessageIdx + 1] : null;
|
|
307
310
|
|
|
308
311
|
if (rawName) {
|
|
309
312
|
doCreate(rawName);
|
|
@@ -371,7 +374,8 @@ function runNew() {
|
|
|
371
374
|
|
|
372
375
|
var result;
|
|
373
376
|
try {
|
|
374
|
-
|
|
377
|
+
const createOpts = customFirstMessage ? { firstMessage: customFirstMessage } : {};
|
|
378
|
+
result = require('./create_agent').createAgent(input, createOpts);
|
|
375
379
|
} catch (err) {
|
|
376
380
|
console.log(R + '创建失败: ' + err.message + NC);
|
|
377
381
|
process.exit(1);
|
|
@@ -1763,6 +1767,7 @@ function runSync(workspaceName) {
|
|
|
1763
1767
|
const targetPyPath = path.join(targetDir, 'sync_workspace.py');
|
|
1764
1768
|
const targetConfigPath = path.join(targetDir, 'config.json');
|
|
1765
1769
|
const sourcePyPath = path.join(__dirname, 'server', 'sync_workspace.py');
|
|
1770
|
+
const sourceSchemaPath = path.join(__dirname, 'server', 'artifacts_schema.py');
|
|
1766
1771
|
|
|
1767
1772
|
// 确保目标目录存在
|
|
1768
1773
|
if (!fs.existsSync(targetDir)) {
|
|
@@ -1771,6 +1776,7 @@ function runSync(workspaceName) {
|
|
|
1771
1776
|
|
|
1772
1777
|
// 同步 py 文件
|
|
1773
1778
|
fs.copyFileSync(sourcePyPath, targetPyPath);
|
|
1779
|
+
fs.copyFileSync(sourceSchemaPath, path.join(targetDir, 'artifacts_schema.py'));
|
|
1774
1780
|
|
|
1775
1781
|
// 读取配置(如果不存在则创建)
|
|
1776
1782
|
let config;
|
|
@@ -1812,8 +1818,11 @@ async function runServer(name) {
|
|
|
1812
1818
|
// 用户目录下的服务目录
|
|
1813
1819
|
const targetDir = path.join(os.homedir(), '.openclaw', 'myclaw', 'server');
|
|
1814
1820
|
const targetPyPath = path.join(targetDir, 'sync_workspace.py');
|
|
1821
|
+
const targetGuardPath = path.join(targetDir, 'myclaw-guard.sh');
|
|
1815
1822
|
const targetConfigPath = path.join(targetDir, 'config.json');
|
|
1816
1823
|
const sourcePyPath = path.join(__dirname, 'server', 'sync_workspace.py');
|
|
1824
|
+
const sourceSchemaPath = path.join(__dirname, 'server', 'artifacts_schema.py');
|
|
1825
|
+
const sourceGuardPath = path.join(__dirname, 'server', 'myclaw-guard.sh');
|
|
1817
1826
|
const pidFile = path.join(os.homedir(), '.openclaw', '.myclaw-sync.pid');
|
|
1818
1827
|
|
|
1819
1828
|
// 0. 杀死旧的 sync_workspace 进程(通过 PID 文件)
|
|
@@ -1834,9 +1843,13 @@ async function runServer(name) {
|
|
|
1834
1843
|
console.log('[Server] 创建目录: ' + targetDir);
|
|
1835
1844
|
}
|
|
1836
1845
|
|
|
1837
|
-
// 2. 覆盖 py
|
|
1846
|
+
// 2. 覆盖 py 文件 & guard 脚本(确保最新)
|
|
1838
1847
|
fs.copyFileSync(sourcePyPath, targetPyPath);
|
|
1848
|
+
fs.copyFileSync(sourceSchemaPath, path.join(targetDir, 'artifacts_schema.py'));
|
|
1839
1849
|
console.log('[Server] 同步脚本: ' + targetPyPath);
|
|
1850
|
+
fs.copyFileSync(sourceGuardPath, targetGuardPath);
|
|
1851
|
+
fs.chmodSync(targetGuardPath, 0o755);
|
|
1852
|
+
console.log('[Server] 守卫脚本: ' + targetGuardPath);
|
|
1840
1853
|
|
|
1841
1854
|
// 3. 确保配置文件存在(如果已有就不动)
|
|
1842
1855
|
let config;
|
|
@@ -1950,6 +1963,7 @@ function showHelp() {
|
|
|
1950
1963
|
console.log(' inject-workspaceAndSoul 替换默认 workspace 的 SOUL.md 提示词');
|
|
1951
1964
|
console.log(' inject-tooldeny deny image_generate + music_generate 内置工具');
|
|
1952
1965
|
console.log(' inject-controlui 注入 controlUi 配置 (allowInsecureAuth + allowedOrigins)');
|
|
1966
|
+
console.log(' all 完整升级: up + patch + server + restart');
|
|
1953
1967
|
console.log(' restart 重启 OpenClaw Gateway');
|
|
1954
1968
|
console.log(' nuke ⚠️ 核弹重置 (需加 --dangerous): 清除数据 + onboard + up + patch + restart');
|
|
1955
1969
|
console.log(' help 显示帮助信息');
|
|
@@ -2007,6 +2021,24 @@ if (!command) {
|
|
|
2007
2021
|
if (detectPlatform() === 'windows') {
|
|
2008
2022
|
runBat();
|
|
2009
2023
|
}
|
|
2024
|
+
} else if (command === 'all') {
|
|
2025
|
+
// 完整升级:升级包 → patch → server → restart
|
|
2026
|
+
console.log('[mc all] 开始完整升级流程...');
|
|
2027
|
+
console.log('');
|
|
2028
|
+
console.log('[1/4] mc up — 升级包 + patch');
|
|
2029
|
+
runUpdate();
|
|
2030
|
+
runPatch();
|
|
2031
|
+
if (detectPlatform() === 'windows') {
|
|
2032
|
+
runBat();
|
|
2033
|
+
}
|
|
2034
|
+
console.log('');
|
|
2035
|
+
console.log('[2/4] mc restart — 重启 Gateway');
|
|
2036
|
+
runRestart();
|
|
2037
|
+
console.log('');
|
|
2038
|
+
console.log('[3/4] mc server — 更新 Python 守护进程');
|
|
2039
|
+
runServer(args[1]);
|
|
2040
|
+
console.log('');
|
|
2041
|
+
console.log('[4/4] 完成 ✅');
|
|
2010
2042
|
} else if (command === 'start') {
|
|
2011
2043
|
runStart();
|
|
2012
2044
|
} else if (command === 'open') {
|
package/package.json
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""
|
|
2
|
+
__MY_ARTIFACTS__.json 的统一初始结构定义
|
|
3
|
+
|
|
4
|
+
所有需要创建或读取 artifacts 配置的模块都应使用此处的函数,
|
|
5
|
+
确保字段一致。
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from datetime import datetime, timezone, timedelta
|
|
9
|
+
|
|
10
|
+
ARTIFACTS_FILENAME = "__MY_ARTIFACTS__.json"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def now_iso():
|
|
14
|
+
"""生成 +08:00 时间格式"""
|
|
15
|
+
tz = timezone(timedelta(hours=8))
|
|
16
|
+
return datetime.now(tz).isoformat()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def create_empty_artifacts(workspace_id, base_url=""):
|
|
20
|
+
"""创建空的 artifacts 初始结构(以 registry.py 为准)"""
|
|
21
|
+
now = now_iso()
|
|
22
|
+
return {
|
|
23
|
+
"workspace_id": workspace_id,
|
|
24
|
+
"title": "我的资源库",
|
|
25
|
+
"release_version": 1,
|
|
26
|
+
"created_at": now,
|
|
27
|
+
"updated_at": now,
|
|
28
|
+
"version": 1,
|
|
29
|
+
"base_url": base_url,
|
|
30
|
+
"preview_path": "index.html",
|
|
31
|
+
"assets": []
|
|
32
|
+
}
|