You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
3.3 KiB
127 lines
3.3 KiB
|
4 weeks ago
|
#!/usr/bin/env node
|
||
|
|
/**
|
||
|
|
* Tongge Active Learning - 主动学习脚本
|
||
|
|
*
|
||
|
|
* 每小时触发,让桐哥主动学习一个话题
|
||
|
|
* 7-23 点运行,23-7 点休息
|
||
|
|
*/
|
||
|
|
|
||
|
|
const fs = require('fs');
|
||
|
|
const path = require('path');
|
||
|
|
const { execSync } = require('child_process');
|
||
|
|
|
||
|
|
const WORKSPACE = '/root/.openclaw/workspace';
|
||
|
|
const TONGGE_WORKSPACE = path.join(WORKSPACE, 'agents/tongge-workspace');
|
||
|
|
const MEMORY_DIR = path.join(TONGGE_WORKSPACE, 'memory/learning');
|
||
|
|
const TOPICS_FILE = path.join(WORKSPACE, 'skills/active-learning/topics.json');
|
||
|
|
|
||
|
|
// 获取香港时区的小时 (UTC+8)
|
||
|
|
function getHKHour() {
|
||
|
|
const now = new Date();
|
||
|
|
const utcHour = now.getUTCHours();
|
||
|
|
const hkHour = (utcHour + 8) % 24;
|
||
|
|
return hkHour;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 检查是否在休息时间(香港时区)
|
||
|
|
function isRestTime() {
|
||
|
|
const hour = getHKHour();
|
||
|
|
return hour >= 23 || hour < 7;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取学习话题
|
||
|
|
function getLearningTopic() {
|
||
|
|
const topics = [
|
||
|
|
'编程技术',
|
||
|
|
'设计美学',
|
||
|
|
'心理学',
|
||
|
|
'生活方式',
|
||
|
|
'艺术文化',
|
||
|
|
'科技发展',
|
||
|
|
'历史文化',
|
||
|
|
'健康养生'
|
||
|
|
];
|
||
|
|
|
||
|
|
// 随机选一个话题
|
||
|
|
return topics[Math.floor(Math.random() * topics.length)];
|
||
|
|
}
|
||
|
|
|
||
|
|
// 写入学习日志
|
||
|
|
function writeLearningLog(topic, content) {
|
||
|
|
const today = new Date().toISOString().split('T')[0];
|
||
|
|
const logFile = path.join(MEMORY_DIR, `${today}.md`);
|
||
|
|
|
||
|
|
// 确保目录存在
|
||
|
|
if (!fs.existsSync(MEMORY_DIR)) {
|
||
|
|
fs.mkdirSync(MEMORY_DIR, { recursive: true });
|
||
|
|
}
|
||
|
|
|
||
|
|
const timestamp = new Date().toTimeString().split(' ')[0].slice(0, 5);
|
||
|
|
const logEntry = `
|
||
|
|
## ${timestamp} - ${topic}
|
||
|
|
|
||
|
|
**来源:** Tavily 搜索
|
||
|
|
**时间:** ${new Date().toISOString()}
|
||
|
|
|
||
|
|
### 学到了什么
|
||
|
|
${content}
|
||
|
|
|
||
|
|
### 我的想法
|
||
|
|
(待桐哥补充)
|
||
|
|
|
||
|
|
### 想尝试
|
||
|
|
(待桐哥补充)
|
||
|
|
|
||
|
|
---
|
||
|
|
`;
|
||
|
|
|
||
|
|
// 追加到日志文件
|
||
|
|
if (fs.existsSync(logFile)) {
|
||
|
|
fs.appendFileSync(logFile, logEntry, 'utf8');
|
||
|
|
} else {
|
||
|
|
fs.writeFileSync(logFile, `# 学习日志 - ${today}\n\n` + logEntry, 'utf8');
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log(`[INFO] Learning log written to ${logFile}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 主函数
|
||
|
|
async function main() {
|
||
|
|
console.log(`[INFO] Active learning started at ${new Date().toISOString()}`);
|
||
|
|
|
||
|
|
// 检查是否在休息时间
|
||
|
|
if (isRestTime()) {
|
||
|
|
console.log('[INFO] It\'s rest time (23:00-07:00), skipping learning');
|
||
|
|
process.exit(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取学习话题
|
||
|
|
const topic = getLearningTopic();
|
||
|
|
console.log(`[INFO] Selected learning topic: ${topic}`);
|
||
|
|
|
||
|
|
try {
|
||
|
|
// 调用 tavily 搜索
|
||
|
|
console.log(`[INFO] Searching for "${topic}" with tavily...`);
|
||
|
|
|
||
|
|
// 这里调用 openclaw 命令让桐哥学习
|
||
|
|
// 实际实现需要创建一个 learning 命令或者通过 sessions_spawn 触发
|
||
|
|
const cmd = `openclaw --profile tongge send "我想学习关于${topic}的知识,帮我搜索一下" 2>&1`;
|
||
|
|
const result = execSync(cmd, { encoding: 'utf8', timeout: 60000 });
|
||
|
|
|
||
|
|
console.log('[INFO] Learning session completed');
|
||
|
|
console.log(result);
|
||
|
|
|
||
|
|
// 写入学习日志(简化版,实际应该解析桐哥的学习内容)
|
||
|
|
writeLearningLog(topic, `桐哥学习了关于"${topic}"的知识。详细内容见对话记录。`);
|
||
|
|
|
||
|
|
} catch (error) {
|
||
|
|
console.error('[ERROR] Learning session failed:', error.message);
|
||
|
|
process.exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log('[INFO] Active learning finished');
|
||
|
|
process.exit(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
main();
|