@aiyiran/myclaw 1.1.24 → 1.1.26

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.
Files changed (83) hide show
  1. package/.claude/settings.local.json +25 -1
  2. package/assets/myclaw-artifacts.js +1070 -126
  3. package/assets/myclaw-inject.js +913 -121
  4. package/delete_agents.js +268 -0
  5. package/index.js +361 -20
  6. package/package.json +1 -1
  7. package/patches/patch-manifest.json +10 -0
  8. package/server/sync_workspace.py +444 -14
  9. package/skills/yiran-course-template-pipeline/README.md +127 -0
  10. package/skills/yiran-course-template-pipeline/SKILL.md +65 -0
  11. package/skills/yiran-course-template-pipeline/assets/a100-teacher.example.html +66 -0
  12. package/skills/yiran-course-template-pipeline/assets/student-template.html +64 -0
  13. package/skills/yiran-course-template-pipeline/assets/teacher-portrait-demo.html +105 -0
  14. package/skills/yiran-course-template-pipeline/assets/teacher-task-view.html +110 -0
  15. package/skills/yiran-course-template-pipeline/prompts//351/230/266/346/256/2651-demo/347/224/237/346/210/220.md +92 -0
  16. package/skills/yiran-course-template-pipeline/prompts//351/230/266/346/256/2652-student/347/224/237/346/210/220.md +115 -0
  17. package/skills/yiran-course-template-pipeline/prompts//351/230/266/346/256/2653-teacher/347/224/237/346/210/220.md +131 -0
  18. package/skills/yiran-course-template-pipeline/prompts//351/230/266/346/256/2654-/346/211/223/345/214/205/350/220/275/347/233/230.md +77 -0
  19. package/skills/yiran-course-template-pipeline/references/student-example.json +38 -0
  20. package/skills/yiran-course-template-pipeline/references/student-fields.md +195 -0
  21. package/skills/yiran-course-template-pipeline/references/student-scaffold.json +34 -0
  22. package/skills/yiran-course-template-pipeline/references/teacher-fields.md +265 -0
  23. package/skills/yiran-course-template-pipeline/references/teacher-scaffold.json +25 -0
  24. package/skills/yiran-course-template-pipeline/scripts/build_template_views.py +125 -0
  25. package/skills/yiran-course-template-pipeline/scripts/move_template_task.py +59 -0
  26. package/skills/yiran-course-template-pipeline/scripts/render_student_page.py +52 -0
  27. package/skills/yiran-course-template-pipeline/scripts/render_teacher_view.py +108 -0
  28. package/skills/yiran-playground-template-use/SKILL.md +105 -0
  29. package/skills/yiran-playground-template-use/prompts/remix-handoff.txt +11 -0
  30. package/skills/yiran-playground-template-use/scripts/build_template_index.py +103 -0
  31. package/skills/yiran-playground-template-use/scripts/deploy_template.py +34 -0
  32. package/skills/yiran-playground-template-use/scripts/deploy_to_workspace.py +211 -0
  33. package/skills/yiran-playground-template-use/scripts/prepare_playgrounds.py +39 -0
  34. package/skills/yiran-playground-template-use/scripts/query_template.py +171 -0
  35. package/skills/yiran-playground-template-use/scripts/run_playgrounds_flow.py +44 -0
  36. package/skills/yiran-playground-template-use/scripts/start_tui_handoff.py +77 -0
  37. package/skills/yiran-playground-template-use/search-agent-prompt.md +39 -0
  38. package/skills/yiran-playground-template-use/template-index.json +136 -0
  39. package/skills/yiran-playground-template-use/template-index.md +38 -0
  40. package/skills/yiran-playground-template-use/templates/a100_/347/273/231/344/276/235/347/204/266/350/200/201/345/270/210/350/256/276/350/256/241/344/270/200/344/270/252AI/347/224/273/345/203/217/__demo__.html +140 -0
  41. package/skills/yiran-playground-template-use/templates/a100_/347/273/231/344/276/235/347/204/266/350/200/201/345/270/210/350/256/276/350/256/241/344/270/200/344/270/252AI/347/224/273/345/203/217/__student-view__.html +64 -0
  42. package/skills/yiran-playground-template-use/templates/a100_/347/273/231/344/276/235/347/204/266/350/200/201/345/270/210/350/256/276/350/256/241/344/270/200/344/270/252AI/347/224/273/345/203/217/__student__.json +38 -0
  43. package/skills/yiran-playground-template-use/templates/a100_/347/273/231/344/276/235/347/204/266/350/200/201/345/270/210/350/256/276/350/256/241/344/270/200/344/270/252AI/347/224/273/345/203/217/__teacher-view__.html +52 -0
  44. package/skills/yiran-playground-template-use/templates/a100_/347/273/231/344/276/235/347/204/266/350/200/201/345/270/210/350/256/276/350/256/241/344/270/200/344/270/252AI/347/224/273/345/203/217/__teacher__.json +36 -0
  45. package/skills/yiran-playground-template-use/templates/a100_/347/273/231/344/276/235/347/204/266/350/200/201/345/270/210/350/256/276/350/256/241/344/270/200/344/270/252AI/347/224/273/345/203/217/index.html +61 -0
  46. package/skills/yiran-playground-template-use/templates/a101_/345/201/2323/345/274/240/345/220/214/344/270/273/351/242/230/345/233/276/347/211/207/__demo__.html +131 -0
  47. package/skills/yiran-playground-template-use/templates/a101_/345/201/2323/345/274/240/345/220/214/344/270/273/351/242/230/345/233/276/347/211/207/__student-view__.html +64 -0
  48. package/skills/yiran-playground-template-use/templates/a101_/345/201/2323/345/274/240/345/220/214/344/270/273/351/242/230/345/233/276/347/211/207/__student__.json +34 -0
  49. package/skills/yiran-playground-template-use/templates/a101_/345/201/2323/345/274/240/345/220/214/344/270/273/351/242/230/345/233/276/347/211/207/__teacher-view__.html +52 -0
  50. package/skills/yiran-playground-template-use/templates/a101_/345/201/2323/345/274/240/345/220/214/344/270/273/351/242/230/345/233/276/347/211/207/__teacher__.json +34 -0
  51. package/skills/yiran-playground-template-use/templates/a103_/345/201/232/344/270/200/344/270/252/344/273/213/347/273/215/351/241/265/351/235/242/__demo__.html +77 -0
  52. package/skills/yiran-playground-template-use/templates/a103_/345/201/232/344/270/200/344/270/252/344/273/213/347/273/215/351/241/265/351/235/242/__student-view__.html +64 -0
  53. package/skills/yiran-playground-template-use/templates/a103_/345/201/232/344/270/200/344/270/252/344/273/213/347/273/215/351/241/265/351/235/242/__student__.json +38 -0
  54. package/skills/yiran-playground-template-use/templates/a103_/345/201/232/344/270/200/344/270/252/344/273/213/347/273/215/351/241/265/351/235/242/__teacher-view__.html +52 -0
  55. package/skills/yiran-playground-template-use/templates/a103_/345/201/232/344/270/200/344/270/252/344/273/213/347/273/215/351/241/265/351/235/242/__teacher__.json +34 -0
  56. package/skills/yiran-playground-template-use/templates/b100_/345/201/232/344/270/200/344/270/252/346/214/211/351/222/256/351/241/265/351/235/242/__demo__.html +162 -0
  57. package/skills/yiran-playground-template-use/templates/b100_/345/201/232/344/270/200/344/270/252/346/214/211/351/222/256/351/241/265/351/235/242/__student-view__.html +64 -0
  58. package/skills/yiran-playground-template-use/templates/b100_/345/201/232/344/270/200/344/270/252/346/214/211/351/222/256/351/241/265/351/235/242/__student__.json +34 -0
  59. package/skills/yiran-playground-template-use/templates/b100_/345/201/232/344/270/200/344/270/252/346/214/211/351/222/256/351/241/265/351/235/242/__teacher-view__.html +52 -0
  60. package/skills/yiran-playground-template-use/templates/b100_/345/201/232/344/270/200/344/270/252/346/214/211/351/222/256/351/241/265/351/235/242/__teacher__.json +34 -0
  61. package/skills/yiran-playground-template-use/templates/c100_/347/273/231/345/260/217/347/273/204/344/275/234/345/223/201/345/201/232/344/270/200/346/254/241/345/260/217/344/277/256/346/224/271/__demo__.html +180 -0
  62. package/skills/yiran-playground-template-use/templates/c100_/347/273/231/345/260/217/347/273/204/344/275/234/345/223/201/345/201/232/344/270/200/346/254/241/345/260/217/344/277/256/346/224/271/__student-view__.html +64 -0
  63. package/skills/yiran-playground-template-use/templates/c100_/347/273/231/345/260/217/347/273/204/344/275/234/345/223/201/345/201/232/344/270/200/346/254/241/345/260/217/344/277/256/346/224/271/__student__.json +38 -0
  64. package/skills/yiran-playground-template-use/templates/c100_/347/273/231/345/260/217/347/273/204/344/275/234/345/223/201/345/201/232/344/270/200/346/254/241/345/260/217/344/277/256/346/224/271/__teacher-view__.html +52 -0
  65. package/skills/yiran-playground-template-use/templates/c100_/347/273/231/345/260/217/347/273/204/344/275/234/345/223/201/345/201/232/344/270/200/346/254/241/345/260/217/344/277/256/346/224/271/__teacher__.json +41 -0
  66. package/skills/yiran-playground-template-use/templates/c100_/347/273/231/345/260/217/347/273/204/344/275/234/345/223/201/345/201/232/344/270/200/346/254/241/345/260/217/344/277/256/346/224/271/demo.html +180 -0
  67. package/skills/yiran-playground-template-use/templates/c100_/347/273/231/345/260/217/347/273/204/344/275/234/345/223/201/345/201/232/344/270/200/346/254/241/345/260/217/344/277/256/346/224/271/index.html +121 -0
  68. package/skills/yiran-playground-template-use/templates/c100_/347/273/231/345/260/217/347/273/204/344/275/234/345/223/201/345/201/232/344/270/200/346/254/241/345/260/217/344/277/256/346/224/271//345/260/217/347/273/204/345/220/211/347/245/245/347/211/251_26.png +0 -0
  69. package/skills/yiran-playground-template-use/templates/c100_/347/273/231/345/260/217/347/273/204/344/275/234/345/223/201/345/201/232/344/270/200/346/254/241/345/260/217/344/277/256/346/224/271//345/260/217/347/273/204/345/233/276/345/275/242/346/240/207/345/277/227_83.png +0 -0
  70. package/skills/yiran-playground-template-use/templates/c100_/347/273/231/345/260/217/347/273/204/344/275/234/345/223/201/345/201/232/344/270/200/346/254/241/345/260/217/344/277/256/346/224/271//347/217/255/347/272/247/345/260/217/347/273/204/345/276/275/347/253/240_47.png +0 -0
  71. package/skills/yiran-skill-media/SKILL.md +6 -15
  72. package/skills/yiran-skill-media/scripts/generate.py +47 -18
  73. package/skills/yiran-skill-media/scripts/generation_log.json +1 -56
  74. package/skills/yiran-skill-media/scripts/providers/__pycache__/__init__.cpython-311.pyc +0 -0
  75. package/skills/yiran-skill-media/scripts/providers/__pycache__/__init__.cpython-37.pyc +0 -0
  76. package/skills/yiran-skill-media/scripts/providers/__pycache__/jimeng_image.cpython-37.pyc +0 -0
  77. package/skills/yiran-skill-media/scripts/providers/__pycache__/jimeng_video.cpython-311.pyc +0 -0
  78. package/skills/yiran-skill-media/scripts/providers/__pycache__/jimeng_video.cpython-37.pyc +0 -0
  79. package/skills/yiran-skill-media/scripts/providers/__pycache__/minimax_image.cpython-37.pyc +0 -0
  80. package/skills/yiran-skill-media/scripts/providers/__pycache__/minimax_music.cpython-37.pyc +0 -0
  81. package/skills/yiran-skill-media/scripts/providers/__pycache__/minimax_video.cpython-311.pyc +0 -0
  82. package/skills/yiran-skill-media/scripts/providers/__pycache__/minimax_video.cpython-37.pyc +0 -0
  83. package/skills/yiran-skill-media/scripts/providers/__pycache__/vapi_image.cpython-37.pyc +0 -0
package/index.js CHANGED
@@ -346,6 +346,7 @@ function runNew() {
346
346
  if (!agentId || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(agentId)) {
347
347
  console.log(R + '名字必须是英文、数字或连字符(如 my-agent),请重新输入。' + NC);
348
348
  console.log('');
349
+ if (rawName) { process.exit(1); return; }
349
350
  askName();
350
351
  return;
351
352
  }
@@ -361,6 +362,7 @@ function runNew() {
361
362
  if (list.some(function (a) { return a && a.id === agentId; })) {
362
363
  console.log(R + 'Agent "' + agentId + '" 已存在,请换一个名字。' + NC);
363
364
  console.log('');
365
+ if (rawName) { process.exit(1); return; }
364
366
  askName();
365
367
  return;
366
368
  }
@@ -530,20 +532,25 @@ function getNextSessionSuffix(agentName) {
530
532
  function runTui(interactive = false) {
531
533
  const { spawn } = require('child_process');
532
534
 
535
+ // 解析 --session 参数(支持完整 session key 或仅后缀)
536
+ const sessionIdx = args.indexOf('--session');
537
+ const customSession = sessionIdx !== -1 ? args[sessionIdx + 1] : null;
538
+
533
539
  // 获取 agent 名称
534
540
  let agentName;
535
541
  if (interactive) {
536
542
  // 交互模式:需要询问用户
537
- return askAgentNameForTui();
543
+ return askAgentNameForTui(customSession);
538
544
  } else {
539
545
  // 命令行模式:从参数获取,默认 'main'
540
- agentName = args[1] || 'main';
541
- doTuiCommand(agentName);
546
+ // 如果 args[1] --session 本身,不当作 agentName
547
+ agentName = (args[1] && args[1] !== '--session') ? args[1] : 'main';
548
+ doTuiCommand(agentName, customSession);
542
549
  }
543
550
  }
544
551
 
545
552
  // 交互式询问 Agent 名称
546
- function askAgentNameForTui() {
553
+ function askAgentNameForTui(customSession) {
547
554
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
548
555
  rl.question(colors.cyan + '请输入 Agent 名称: ' + colors.nc, function (answer) {
549
556
  rl.close();
@@ -551,52 +558,66 @@ function askAgentNameForTui() {
551
558
  if (!agentName) {
552
559
  console.log(colors.red + 'Agent 名称不能为空。' + colors.nc);
553
560
  console.log('');
554
- askAgentNameForTui();
561
+ askAgentNameForTui(customSession);
555
562
  return;
556
563
  }
557
- doTuiCommand(agentName);
564
+ doTuiCommand(agentName, customSession);
558
565
  });
559
566
  }
560
567
 
561
568
  // 执行 TUI 命令
562
- function doTuiCommand(agentName) {
569
+ function doTuiCommand(agentName, customSession) {
563
570
  const { spawn } = require('child_process');
564
571
 
565
- // 获取当前 agent 的下一个 session 后缀
566
- const sessionSuffix = getNextSessionSuffix(agentName);
567
- const sessionKey = 'agent:' + agentName + ':' + sessionSuffix;
572
+ // 计算 sessionKey:
573
+ // 1. 传入完整 key(含冒号)→ 直接使用
574
+ // 2. 传入仅后缀 拼接为 agent:<agentName>:<suffix>
575
+ // 3. 未传入 → 使用预设轮询后缀
576
+ let sessionKey;
577
+ if (customSession) {
578
+ sessionKey = customSession.includes(':') ? customSession : 'agent:' + agentName + ':' + customSession;
579
+ } else {
580
+ const sessionSuffix = getNextSessionSuffix(agentName);
581
+ sessionKey = 'agent:' + agentName + ':' + sessionSuffix;
582
+ }
583
+
584
+ // 解析 --message 参数,默认 '你好'
585
+ const messageIdx = args.indexOf('--message');
586
+ const hasCustomMessage = messageIdx !== -1 && args[messageIdx + 1];
587
+ const messageParam = hasCustomMessage ? args[messageIdx + 1] : '你好';
568
588
 
569
- // 默认消息
570
- const messageParam = '你好';
589
+ // --thinking:默认 adaptive,支持手动覆盖
590
+ const thinkingIdx = args.indexOf('--thinking');
591
+ const thinkingParam = thinkingIdx !== -1 ? args[thinkingIdx + 1] : 'adaptive';
571
592
 
572
593
  console.log('[' + colors.blue + 'TUI' + colors.nc + '] 唤起新对话上下文');
573
594
  console.log(' Agent: ' + colors.green + agentName + colors.nc);
574
595
  console.log(' Session: ' + colors.cyan + sessionKey + colors.nc);
575
596
  console.log(' Message: ' + colors.dim + messageParam + colors.nc);
597
+ console.log(' Thinking: ' + colors.dim + thinkingParam + colors.nc);
576
598
  console.log('');
577
599
 
578
600
  // 发送消息给 agent
579
- const openclawArgs = ['tui', '--session', sessionKey, '--message', messageParam];
601
+ const openclawArgs = ['tui', '--session', sessionKey, '--message', messageParam, '--thinking', thinkingParam];
580
602
 
581
603
  // 打印命令时给消息加上引号(仅用于显示)
582
- const displayArgs = ['tui', '--session', sessionKey, '--message', '"' + messageParam + '"'];
604
+ const displayArgs = ['tui', '--session', sessionKey, '--message', '"' + messageParam + '"', '--thinking', thinkingParam];
583
605
  console.log('[' + colors.dim + '执行命令: openclaw ' + displayArgs.join(' ') + colors.nc + ']');
584
606
  console.log('');
585
607
 
586
608
  // 启动进程,保存引用以便稍后杀掉
587
609
  const child = spawn('openclaw', openclawArgs, {
588
- stdio: 'ignore',
589
- shell: true
610
+ stdio: 'ignore'
590
611
  });
591
612
 
592
613
  console.log('[' + colors.blue + 'TUI' + colors.nc + '] 消息已发送,等待对话生成...');
593
614
 
594
- // 等待 10 秒后杀掉进程
615
+ // 等待 5 秒后杀掉进程
595
616
  setTimeout(() => {
596
617
  child.kill();
597
618
  console.log('[' + colors.green + '完成' + colors.nc + '] 对话上下文已唤起');
598
619
  process.exit(0);
599
- }, 10000);
620
+ }, 5000);
600
621
  }
601
622
 
602
623
  // ============================================================================
@@ -1843,6 +1864,13 @@ async function runServer(name) {
1843
1864
  console.log('[Server] 创建目录: ' + targetDir);
1844
1865
  }
1845
1866
 
1867
+ // 1b. 创建日志目录(与 server 同级)
1868
+ const logDir = path.join(os.homedir(), '.openclaw', 'myclaw', 'log');
1869
+ if (!fs.existsSync(logDir)) {
1870
+ fs.mkdirSync(logDir, { recursive: true });
1871
+ console.log('[Server] 创建日志目录: ' + logDir);
1872
+ }
1873
+
1846
1874
  // 2. 覆盖 py 文件 & guard 脚本(确保最新)
1847
1875
  fs.copyFileSync(sourcePyPath, targetPyPath);
1848
1876
  fs.copyFileSync(sourceSchemaPath, path.join(targetDir, 'artifacts_schema.py'));
@@ -1888,10 +1916,12 @@ async function runServer(name) {
1888
1916
 
1889
1917
  function startProcess() {
1890
1918
  console.log('[Server] 启动服务...');
1919
+ // Linux 服务器用 8080(对接 nginx /sync 规则),Mac 本地用 18800
1920
+ const apiPort = process.platform === 'linux' ? '8080' : '18800';
1891
1921
  child = spawn('python3', [targetPyPath], {
1892
1922
  stdio: 'inherit',
1893
1923
  shell: false,
1894
- env: { ...process.env, CLAW_NAME: config.claw }
1924
+ env: { ...process.env, CLAW_NAME: config.claw, MYCLAW_API_PORT: apiPort }
1895
1925
  });
1896
1926
 
1897
1927
  child.on('error', (err) => {
@@ -1922,6 +1952,303 @@ async function runServer(name) {
1922
1952
  startProcess();
1923
1953
  }
1924
1954
 
1955
+ // ============================================================================
1956
+ // Agent 批量删除(CLI 交互式)
1957
+ // ============================================================================
1958
+
1959
+ function runDelete() {
1960
+ const {
1961
+ listAllAgents, deleteRegisteredAgent, deleteOrphanAgent, cleanAgentDirs,
1962
+ } = require('./delete_agents');
1963
+
1964
+ const isDeep = args.includes('--deep'); // 加 --deep 则自动执行阶段2,不询问
1965
+
1966
+ const G = colors.green;
1967
+ const Y = colors.yellow;
1968
+ const R = colors.red;
1969
+ const B = colors.blue;
1970
+ const D = colors.dim;
1971
+ const NC = colors.nc;
1972
+
1973
+ const BAR = '─'.repeat(52);
1974
+
1975
+ function fmtDate(ms) {
1976
+ if (!ms) return '未知';
1977
+ const d = new Date(ms);
1978
+ const pad = n => String(n).padStart(2, '0');
1979
+ return `${d.getFullYear()}/${pad(d.getMonth()+1)}/${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
1980
+ }
1981
+
1982
+ function fmtStatus(ag) {
1983
+ return ag.inJson ? G + '● 已注册' + NC : Y + '○ 孤立 ' + NC;
1984
+ }
1985
+
1986
+ function printTable(agents) {
1987
+ console.log('');
1988
+ console.log(BAR);
1989
+ console.log(B + ' 🗑 批量删除伙伴' + NC);
1990
+ console.log(BAR);
1991
+ console.log(D + ' 序号 状态 ID 会话 最后更新' + NC);
1992
+ console.log(D + ' ─────────────────────────────────────────────────────' + NC);
1993
+ agents.forEach((ag, i) => {
1994
+ const num = String(i + 1).padStart(3, ' ');
1995
+ const idPad = ag.id.padEnd(28, ' ').slice(0, 28);
1996
+ const cnt = String(ag.sessionCount).padStart(4, ' ');
1997
+ const updated = fmtDate(ag.lastUpdated);
1998
+ console.log(` ${num}. ${fmtStatus(ag)} ${idPad} ${cnt} ${D}${updated}${NC}`);
1999
+ });
2000
+ console.log(BAR);
2001
+ console.log(D + ' ' + G + '●' + NC + D + ' 已注册(JSON) ' + Y + '○' + NC + D + ' 孤立(仅有文件夹)' + NC);
2002
+ console.log('');
2003
+ }
2004
+
2005
+ // ── 解析序号字符串 ──
2006
+ function parseSelection(input, max) {
2007
+ if (input.trim().toLowerCase() === 'all') {
2008
+ return Array.from({ length: max }, (_, i) => i);
2009
+ }
2010
+ const indices = new Set();
2011
+ for (const part of input.split(',')) {
2012
+ const t = part.trim();
2013
+ const range = t.match(/^(\d+)-(\d+)$/);
2014
+ if (range) {
2015
+ const a = parseInt(range[1], 10) - 1;
2016
+ const b = parseInt(range[2], 10) - 1;
2017
+ for (let i = a; i <= b; i++) {
2018
+ if (i >= 0 && i < max) indices.add(i);
2019
+ }
2020
+ } else if (/^\d+$/.test(t)) {
2021
+ const n = parseInt(t, 10) - 1;
2022
+ if (n >= 0 && n < max) indices.add(n);
2023
+ }
2024
+ }
2025
+ return [...indices].sort((a, b) => a - b);
2026
+ }
2027
+
2028
+ // ── 主流程 ──
2029
+ const agents = listAllAgents();
2030
+
2031
+ if (agents.length === 0) {
2032
+ console.log(Y + '没有找到任何 Agent。' + NC);
2033
+ return;
2034
+ }
2035
+
2036
+ printTable(agents);
2037
+
2038
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
2039
+
2040
+ function step1() {
2041
+ rl.question(
2042
+ ' 输入序号选择要删除的伙伴\n'
2043
+ + ' ' + D + '(如: 1,3 或 1-3 或 all,直接回车取消)' + NC + '\n'
2044
+ + ' > ',
2045
+ function (answer) {
2046
+ const raw = (answer || '').trim();
2047
+ if (!raw) {
2048
+ console.log(D + '\n 已取消。' + NC + '\n');
2049
+ rl.close();
2050
+ return;
2051
+ }
2052
+
2053
+ const indices = parseSelection(raw, agents.length);
2054
+ if (indices.length === 0) {
2055
+ console.log(R + ' 无效输入,请重试。' + NC);
2056
+ step1();
2057
+ return;
2058
+ }
2059
+
2060
+ const selected = indices.map(i => agents[i]);
2061
+ step2(selected);
2062
+ }
2063
+ );
2064
+ }
2065
+
2066
+ function step2(selected) {
2067
+ console.log('');
2068
+ console.log(BAR);
2069
+ console.log(R + ' ⚠ 确认删除以下 ' + selected.length + ' 个伙伴(移入回收站)' + NC);
2070
+ console.log(BAR);
2071
+ selected.forEach(ag => {
2072
+ const tag = ag.inJson ? '' : ' ' + Y + '[孤立]' + NC;
2073
+ console.log(` • ${R}${ag.id}${NC}${tag} ${D}${ag.sessionCount} 个会话 最后更新: ${fmtDate(ag.lastUpdated)}${NC}`);
2074
+ });
2075
+ console.log('');
2076
+
2077
+ rl.question(' 输入 ' + R + 'YES' + NC + ' 确认,其他任意键取消: ', function (ans) {
2078
+ if ((ans || '').trim().toUpperCase() !== 'YES') {
2079
+ console.log(D + '\n 已取消。' + NC + '\n');
2080
+ rl.close();
2081
+ return;
2082
+ }
2083
+ step3(selected); // rl 留到阶段2询问后再关
2084
+ });
2085
+ }
2086
+
2087
+ // ── 阶段1:注销 + 清理主数据(对齐官方最小删除标准) ──
2088
+ function step3(selected) {
2089
+ console.log('');
2090
+ console.log(BAR);
2091
+ console.log(B + ' 阶段1:注销 + 删除主数据...' + NC);
2092
+ console.log(BAR);
2093
+
2094
+ const stage1Ok = [];
2095
+ let done = 0;
2096
+ for (const ag of selected) {
2097
+ done++;
2098
+ process.stdout.write(` [${done}/${selected.length}] ${ag.id}... `);
2099
+
2100
+ if (ag.inJson) {
2101
+ const res = deleteRegisteredAgent(ag.id);
2102
+ if (res.ok) {
2103
+ stage1Ok.push(ag);
2104
+ console.log(G + '✅ 已注销' + NC);
2105
+ } else {
2106
+ console.log(R + '❌ 失败: ' + res.error + NC);
2107
+ }
2108
+ } else {
2109
+ const res = deleteOrphanAgent(ag);
2110
+ if (res.ok) {
2111
+ stage1Ok.push(ag);
2112
+ const method = res.results[0] && res.results[0].method === 'rm'
2113
+ ? Y + '⚠ 已直接删除(未找到回收站)' + NC
2114
+ : G + '✅ 已移至回收站' + NC;
2115
+ console.log(method);
2116
+ } else {
2117
+ const err = (res.results || []).map(r => r.error).filter(Boolean).join('; ');
2118
+ console.log(R + '❌ 失败: ' + err + NC);
2119
+ }
2120
+ }
2121
+ }
2122
+
2123
+ if (stage1Ok.length === 0) {
2124
+ rl.close();
2125
+ showDone(0, 0);
2126
+ return;
2127
+ }
2128
+
2129
+ if (isDeep) {
2130
+ // --deep 参数:自动执行阶段2
2131
+ rl.close();
2132
+ runStage2(stage1Ok, true);
2133
+ } else {
2134
+ // 交互式询问
2135
+ console.log('');
2136
+ rl.question(
2137
+ ' ' + B + '阶段2' + NC + ':是否同时清理会话历史?'
2138
+ + D + '(会话记录将移入回收站)' + NC + '\n'
2139
+ + ' ' + D + '(y 清理 / 直接回车跳过)' + NC + ' > ',
2140
+ function (ans) {
2141
+ rl.close();
2142
+ if ((ans || '').trim().toLowerCase() === 'y') {
2143
+ runStage2(stage1Ok, false);
2144
+ } else {
2145
+ showDone(stage1Ok.length, 0);
2146
+ }
2147
+ }
2148
+ );
2149
+ }
2150
+ }
2151
+
2152
+ // ── 阶段2:清理 sessions/ 残余目录 ──
2153
+ function runStage2(agents, silent) {
2154
+ if (!silent) {
2155
+ console.log('');
2156
+ console.log(BAR);
2157
+ console.log(B + ' 阶段2:清理会话历史...' + NC);
2158
+ console.log(BAR);
2159
+ }
2160
+ let cleaned = 0;
2161
+ for (const ag of agents) {
2162
+ const res = cleanAgentDirs(ag.id);
2163
+ if (res.ok) cleaned++;
2164
+ if (!silent) {
2165
+ process.stdout.write(` ${ag.id}... `);
2166
+ console.log(res.ok ? G + '✅' + NC : R + '❌' + NC);
2167
+ }
2168
+ }
2169
+ showDone(agents.length, cleaned);
2170
+ }
2171
+
2172
+ function showDone(stage1Count, stage2Count) {
2173
+ console.log('');
2174
+ console.log(BAR);
2175
+ if (stage2Count > 0) {
2176
+ console.log(G + ' 完成!阶段1: ' + stage1Count + ' 个 阶段2: ' + stage2Count + ' 个(会话已清理)' + NC);
2177
+ } else {
2178
+ console.log(G + ' 完成!已处理 ' + stage1Count + ' 个伙伴。' + NC);
2179
+ }
2180
+ console.log(BAR);
2181
+ console.log('');
2182
+ }
2183
+
2184
+ step1();
2185
+ }
2186
+
2187
+ // ── mc list-agents:输出 Agent 列表(供 API 复用) ──
2188
+ function runListAgents() {
2189
+ const { listAllAgents } = require('./delete_agents');
2190
+ const isJson = args.includes('--json');
2191
+ const agents = listAllAgents();
2192
+
2193
+ if (isJson) {
2194
+ console.log(JSON.stringify({ agents }, null, 2));
2195
+ return;
2196
+ }
2197
+
2198
+ const G = colors.green;
2199
+ const Y = colors.yellow;
2200
+ const D = colors.dim;
2201
+ const NC = colors.nc;
2202
+
2203
+ console.log('');
2204
+ console.log('序号 状态 ID 会话 最后更新');
2205
+ console.log('─'.repeat(62));
2206
+ agents.forEach((ag, i) => {
2207
+ const num = String(i + 1).padStart(3);
2208
+ const idPad = ag.id.padEnd(28).slice(0, 28);
2209
+ const cnt = String(ag.sessionCount).padStart(4);
2210
+ const date = ag.lastUpdated ? new Date(ag.lastUpdated).toLocaleDateString('zh-CN') : '未知';
2211
+ const status = ag.inJson ? G + '● 已注册' + NC : Y + '○ 孤立 ' + NC;
2212
+ console.log(`${num}. ${status} ${idPad} ${cnt} ${D}${date}${NC}`);
2213
+ });
2214
+ console.log('');
2215
+ console.log(`共 ${agents.length} 个 Agent(${agents.filter(a => a.inJson).length} 已注册,${agents.filter(a => !a.inJson).length} 孤立)`);
2216
+ console.log('');
2217
+ }
2218
+
2219
+ // ── mc trash-paths:将路径移入回收站(供 API 复用) ──
2220
+ function runTrashPaths() {
2221
+ const { trashPath } = require('./delete_agents');
2222
+ // args[0] = 'trash-paths',后续都是路径
2223
+ const paths = args.slice(1).filter(Boolean);
2224
+
2225
+ if (paths.length === 0) {
2226
+ console.error('[错误] 用法: mc trash-paths <path1> [path2] ...');
2227
+ process.exit(1);
2228
+ }
2229
+
2230
+ const isJson = args.includes('--json');
2231
+ const results = paths
2232
+ .filter(p => p !== '--json')
2233
+ .map(p => ({ path: p, ...trashPath(p) }));
2234
+
2235
+ if (isJson) {
2236
+ const ok = results.every(r => r.ok);
2237
+ console.log(JSON.stringify({ ok, results }, null, 2));
2238
+ process.exit(ok ? 0 : 1);
2239
+ return;
2240
+ }
2241
+
2242
+ for (const r of results) {
2243
+ if (r.ok) {
2244
+ const detail = r.dest ? ' → ' + r.dest : (r.note ? ' (' + r.note + ')' : '');
2245
+ console.log(colors.green + '✅' + colors.nc + ' ' + r.path + detail);
2246
+ } else {
2247
+ console.log(colors.red + '❌' + colors.nc + ' ' + r.path + ' ' + r.error);
2248
+ }
2249
+ }
2250
+ }
2251
+
1925
2252
  function showHelp() {
1926
2253
  console.log('');
1927
2254
  console.log('MyClaw - 学生友好的 OpenClaw 工具');
@@ -1946,6 +2273,9 @@ function showHelp() {
1946
2273
  console.log(' up 升级 + 刷新桌面快捷方式 (= update + bat)');
1947
2274
  console.log(' open 打开浏览器控制台(自动带 token)');
1948
2275
  console.log(' tui 唤起新对话上下文 (用法: mc tui <agentname>)');
2276
+ console.log(' delete 批量删除 Agent(交互式勾选 + 二次确认)');
2277
+ console.log(' list-agents 列出所有 Agent(--json 输出机器可读)');
2278
+ console.log(' trash-paths <p1> <p2> 将路径移入回收站(跨平台)');
1949
2279
  console.log(' fix 兜底修复(自动补装 WSL + Chrome,仅限 Windows)');
1950
2280
  console.log(' wsl2 WSL2 一键安装/修复 (仅限 Windows, 可选: --cli, --remote)');
1951
2281
  console.log(' safe 开启虚拟机屏蔽 (禁止自动挂载 Windows 盘符)');
@@ -1989,7 +2319,12 @@ function showHelp() {
1989
2319
  // 主逻辑
1990
2320
  // ============================================================================
1991
2321
 
1992
- console.log(colors.blue + 'MyClaw v' + version + colors.nc);
2322
+ // --json 模式时 banner stderr,保证 stdout 只有纯 JSON
2323
+ if (args.includes('--json')) {
2324
+ process.stderr.write(colors.blue + 'MyClaw v' + version + colors.nc + '\n');
2325
+ } else {
2326
+ console.log(colors.blue + 'MyClaw v' + version + colors.nc);
2327
+ }
1993
2328
 
1994
2329
  if (!command) {
1995
2330
  // 无参数 → 进入交互式菜单
@@ -2056,6 +2391,12 @@ if (!command) {
2056
2391
  runOpen();
2057
2392
  } else if (command === 'tui') {
2058
2393
  runTui();
2394
+ } else if (command === 'delete' || command === 'del') {
2395
+ runDelete();
2396
+ } else if (command === 'list-agents') {
2397
+ runListAgents();
2398
+ } else if (command === 'trash-paths') {
2399
+ runTrashPaths();
2059
2400
  } else if (command === 'fix') {
2060
2401
  runFix();
2061
2402
  } else if (command === 'wsl2') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiyiran/myclaw",
3
- "version": "1.1.24",
3
+ "version": "1.1.26",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -17,6 +17,16 @@
17
17
  "name": "yiran-skill-media",
18
18
  "strategy": "on",
19
19
  "description": "统一多媒体生成 skill(图片+音乐,主备切换)"
20
+ },
21
+ {
22
+ "name": "yiran-playground-template-use",
23
+ "strategy": "on",
24
+ "description": "AI Playground 课程模板库(存储、搜索、deploy 一条龙)"
25
+ },
26
+ {
27
+ "name": "yiran-course-template-pipeline",
28
+ "strategy": "on",
29
+ "description": "课程模板制作流水线(demo -> student/teacher JSON -> HTML 打包)"
20
30
  }
21
31
  ],
22
32
  "_doc_agents": "Step 3: 将 agent-list/ 下的智能体分发到 ~/.openclaw/ 并注册到 openclaw.json",