b9de3665d9
Phase 1 ✅ CLI 框架 + 配置系统 - clap 子命令: login / listen / send / whoami / usage - config.json + env var 替换 - tracing 日志系统 - state 持久化(auth/runtime 文件存 + PostgreSQL) Phase 2 ✅ 微信通道 - wechat::client — 完整 iLink Bot HTTP API 实现 - 扫码登录(终端二维码 + 轮询状态) - 长轮询 getupdates / 消息收发 / 监听注册 Phase 3 ✅ AI 对话(纯文本 + function calling) - LlmProvider trait: DeepSeek + LM Studio 实现 - SSE 流式解析(text / reasoning / tool_calls delta / usage) - Conversation: 消息历史 + chat / chat_with_tools 工具循环 Phase 4 ✅ PostgreSQL 集成 - app_state(认证 KV 存储) - chat_records(消息收发记录) - llm_usage(Token 用量统计缓存命中率) - user_memories(长期记忆持久化) - pending_approvals(审批确认码) - scheduled_tasks(定时任务表) Phase 5 ✅ 一切皆 Skill(工具系统) - SkillRegistry: 系统 + 用户 skills 双目录合并 - SKILL.md 解析器 + 子进程执行器(stdin JSON → stdout) - 9 个系统 Skills: datetime / weather / search / email / shell / schedule / memos / read_memories / read_summaries - ApprovalManager: High 风险技能 → 确认码审批(透明模式) - High 风险技能:确认码审批(透明模式) Phase 6 ✅ 定时任务调度器 上下文管理 - ChatSession: checkpoint + token budget (28K) + summaries - Token 估算器(中英文自适应) - 12h 空闲 → trigger_idle_summary(不入会话) - Budget 溢出 → trigger_overflow_summary(入会话 + drain 旧消息) - Summarizer: LLM 生成自然语言摘要(fallback 简单截断) - 长期记忆 / 摘要 通过 read_memories / read_summaries 工具按需读取 工具调用日志 + Token 统计 - INFO: 工具名 + 参数 + 结果摘要 - DEBUG: 子进程 exit/stdout/stderr - ias usage --since --until --model 查看用量和缓存命中率
91 lines
3.0 KiB
Bash
Executable File
91 lines
3.0 KiB
Bash
Executable File
#!/usr/bin/env node
|
|
// 邮件工具(IMAP 收发)
|
|
// 通过 stdin 接收 JSON 参数
|
|
let input = '';
|
|
process.stdin.on('data', (chunk) => input += chunk);
|
|
process.stdin.on('end', async () => {
|
|
try {
|
|
const params = JSON.parse(input.trim() || '{}');
|
|
const action = params.action || 'list_unread';
|
|
const limit = params.limit || 5;
|
|
|
|
const host = process.env.EMAIL_IMAP_HOST;
|
|
const port = parseInt(process.env.EMAIL_IMAP_PORT || '993');
|
|
const user = process.env.EMAIL_IMAP_USER;
|
|
const password = process.env.EMAIL_IMAP_PASSWORD;
|
|
|
|
if (!host || !user || !password) {
|
|
console.log('请设置 EMAIL_IMAP_HOST, EMAIL_IMAP_USER, EMAIL_IMAP_PASSWORD');
|
|
process.exit(1);
|
|
}
|
|
|
|
// 使用 openssl s_client 连接 IMAP over SSL
|
|
// 简单实现:列出收件箱最近 N 封邮件摘要
|
|
const net = require('net');
|
|
const tls = require('tls');
|
|
|
|
const socket = tls.connect(port, host, { rejectUnauthorized: false }, () => {
|
|
let buf = '';
|
|
let step = 0;
|
|
let tag = 0;
|
|
|
|
function cmd(line) {
|
|
tag++;
|
|
socket.write(`A${tag} ${line}\r\n`);
|
|
return `A${tag}`;
|
|
}
|
|
|
|
socket.on('data', (data) => {
|
|
buf += data.toString('utf-8');
|
|
// 简化处理:等服务器就绪后依次发命令
|
|
if (step === 0 && buf.includes('OK')) {
|
|
step = 1;
|
|
cmd(`LOGIN "${user}" "${password}"`);
|
|
} else if (step === 1 && buf.includes(`A1 OK`)) {
|
|
step = 2;
|
|
cmd('SELECT INBOX');
|
|
} else if (step === 2 && buf.includes(`A2 OK`)) {
|
|
step = 3;
|
|
cmd(`FETCH 1:${limit} (FLAGS INTERNALDATE BODY.PEEK[HEADER.FIELDS (SUBJECT FROM DATE)])`);
|
|
} else if (step === 3 && buf.includes(`A3 OK`)) {
|
|
step = 4;
|
|
// 解析结果
|
|
const lines = buf.split('\n').filter(l => l.trim());
|
|
const results = [];
|
|
let current = {};
|
|
for (const line of lines) {
|
|
if (line.match(/^\* \d+ FETCH/)) {
|
|
if (current.subject) results.push(current);
|
|
current = {};
|
|
}
|
|
const subjMatch = line.match(/^SUBJECT: (.+)$/i);
|
|
const fromMatch = line.match(/^FROM: (.+)$/i);
|
|
const dateMatch = line.match(/^DATE: (.+)$/i);
|
|
if (subjMatch) current.subject = subjMatch[1].trim();
|
|
if (fromMatch) current.from = fromMatch[1].trim();
|
|
if (dateMatch) current.date = dateMatch[1].trim();
|
|
}
|
|
if (current.subject) results.push(current);
|
|
|
|
console.log(`最近 ${results.length} 封邮件:`);
|
|
results.forEach((r, i) => {
|
|
console.log(`\n${i+1}. 主题: ${r.subject || '(无主题)'}`);
|
|
console.log(` 发件人: ${r.from || '未知'}`);
|
|
console.log(` 时间: ${r.date || '未知'}`);
|
|
});
|
|
cmd('LOGOUT');
|
|
}
|
|
});
|
|
});
|
|
|
|
socket.setTimeout(15000, () => {
|
|
console.log('连接 IMAP 超时');
|
|
process.exit(1);
|
|
});
|
|
|
|
} catch (e) {
|
|
console.log(`邮件查询失败: ${e.message}`);
|
|
process.exit(1);
|
|
}
|
|
});
|