docs: 更新PROJECTS.md添加技术论坛项目记录
This commit is contained in:
54
MEMORY.md
54
MEMORY.md
@@ -93,12 +93,66 @@ git push origin v1.0.0
|
||||
| PDF翻译助手 V2 | 本地 | 19000 | ✅ 运行中 |
|
||||
| 碎片信息记录 | 本地 | 19009 | ✅ 运行中 |
|
||||
| ParamHub Python | 本地 | 19010 | ✅ 运行中 |
|
||||
| 项目服务管理面板 | 本地 | 19013 | ✅ 运行中 |
|
||||
| 网页助手插件 | /coder/web-context-extension | - | 📦 已完成 |
|
||||
| 磁盘大文件扫描 | 本地 | - | 📦 已完成 |
|
||||
|
||||
---
|
||||
|
||||
## 更新日志
|
||||
|
||||
### 2026-04-12
|
||||
- 磁盘大文件扫描工具 v1.0.0:智能扫描找出大文件和大目录
|
||||
- 自动跳过零碎目录(node_modules, .git, venv等)
|
||||
- 文件数量阈值判断(超过阈值视为程序包)
|
||||
- 大小阈值过滤(小目录不深入)
|
||||
- 按大小排序,树形展示
|
||||
- 跨平台:Windows/Linux/macOS
|
||||
- Git仓库: http://192.168.2.8:12007/coder/disk-scanner
|
||||
- AI对话系统 v2.0.0:架构重构
|
||||
- 端口: 19020
|
||||
- 大模型池管理:多LLM Provider配置
|
||||
- Agent管理:系统设定、思考功能开关
|
||||
- 渠道独立:网页端/Matrix独立绑定Agent
|
||||
- 思考功能:支持原生思考模型,兼容无思考功能模型
|
||||
- Git仓库: http://192.168.2.8:12007/coder/ai-chat-system v2.0.0
|
||||
- 多智能体竞标调度系统 v1.0.0:基于邮件方案实现
|
||||
- 端口: 19015
|
||||
- 核心组件:Orchestrator(规划Agent)、Worker(执行Agent)、TaskBoard(任务公告板)
|
||||
- 功能:竞标机制、动态调度、智能容错、质量保证
|
||||
- 默认Agent:代码专家、搜索专家、写作专家、分析专家
|
||||
- Web界面:首页、请求列表、任务列表、Agent管理
|
||||
- Git仓库: http://192.168.2.8:12007/coder/multi-agent-bidding
|
||||
- Xian Favor 收藏系统 v1.0.0:支持命令行、API、Web三种操作模式
|
||||
- 端口: 19014
|
||||
- 功能:文本笔记、链接收藏、专栏订阅、待办事项管理
|
||||
- 标签系统:灵活分类,支持多标签
|
||||
- 状态管理:待办支持待处理/进行中/已完成
|
||||
- 优先级:低/中/高/紧急
|
||||
- 截止日期:待办支持设置截止日期
|
||||
- 快速搜索:全文搜索标题、内容、备注
|
||||
- Git仓库: http://192.168.2.8:12007/coder/xian-favor
|
||||
|
||||
### 2026-04-11
|
||||
- PDF翻译助手 V2 v2.1.0:系统配置支持动态增删用户类型和会员套餐
|
||||
- 新增 UserTypeConfig 模型:用户类型配置支持动态增删
|
||||
- 新增 MembershipPlanConfig 模型:会员套餐配置支持动态增删
|
||||
- 用户类型管理页面:添加、编辑、删除、启用/禁用用户类型
|
||||
- 会员套餐管理页面:添加、编辑、删除、上架/下架、推荐套餐
|
||||
- 功能权限配置:支持选择功能列表
|
||||
- 项目服务管理面板 v1.0.0:统一管理所有项目和服务
|
||||
- 端口: 19013
|
||||
- 功能: 项目列表、状态检测、启动/停止/重启控制、日志查看
|
||||
- 配置文件: projects.json 便于扩展新项目
|
||||
- Git仓库: http://192.168.2.8:12007/coder/project-panel
|
||||
|
||||
### 2026-04-10
|
||||
- 创建 Web服务监控系统(每20分钟检查8个服务,邮件通知)
|
||||
- 配置 Cron 定时任务
|
||||
- 扩展邮件技能:新增 IMAP 接收邮件功能,支持查看未读邮件和文本附件
|
||||
- 创建 A股板块监控系统(东方财富API,异动检测,邮件通知)
|
||||
- 创建邮件收件箱管理系统 (`works/mailbox/`):同步、存储、状态追踪、归档
|
||||
|
||||
### 2026-04-09
|
||||
- 创建 PROJECTS.md 项目记录文件
|
||||
- 创建邮件发送技能 email-sender
|
||||
|
||||
259
PROJECTS.md
259
PROJECTS.md
@@ -14,9 +14,14 @@
|
||||
| 4 | 碎片信息记录 | Web | 19009 | ✅ 运行中 | 2026-04-09 |
|
||||
| 5 | ParamHub Python版 | Web | 19010 | ✅ 运行中 | 2026-04-09 |
|
||||
| 6 | LLM Proxy | Web | 19007/19008 | ✅ 运行中 | 2026-04-10 |
|
||||
| 7 | 网页助手插件 | Extension | - | 📦 已完成 | 2026-04-08 |
|
||||
| 8 | A股历史数据系统 | CLI | - | 🔄 优化中 | 2026-04-09 |
|
||||
| 9 | Web服务监控 | Cron | - | ✅ 运行中 | 2026-04-10 |
|
||||
| 7 | 项目服务管理面板 | Web | 19013 | ✅ 运行中 | 2026-04-11 |
|
||||
| 8 | 网页助手插件 | Extension | - | 📦 已完成 | 2026-04-08 |
|
||||
| 9 | A股历史数据系统 | CLI | - | 🔄 优化中 | 2026-04-09 |
|
||||
| 10 | Web服务监控 | Cron | - | ✅ 运行中 | 2026-04-10 |
|
||||
| 11 | A股板块监控 | Cron | - | ✅ 运行中 | 2026-04-10 |
|
||||
| 12 | AI对话系统 V2 | Web | 19020 | ✅ 运行中 | 2026-04-12 |
|
||||
| 13 | 磁盘大文件扫描 | CLI | - | 📦 已完成 | 2026-04-12 |
|
||||
| 14 | 技术论坛 | Web | 19004/19005 | ✅ 已修复 | 2026-04-12 |
|
||||
|
||||
---
|
||||
|
||||
@@ -169,12 +174,23 @@ curl -s http://localhost:19010/api/categories
|
||||
|
||||
**Git仓库**: http://192.168.2.8:12007/coder/param-hub-python
|
||||
|
||||
**版本**: v0.3.1
|
||||
**版本**: v1.2.0
|
||||
|
||||
**v1.2.0 新功能**:
|
||||
- 网站配置管理:后台可修改网站名称、备案号、页脚文字等
|
||||
- 配置前台自动读取并显示
|
||||
|
||||
**v1.1.0 新功能**:
|
||||
- 智能添加:粘贴文本自动解析为结构化数据(大模型API)
|
||||
- 展示开关:各分类和产品支持显示/隐藏控制
|
||||
- 原始数据保留:智能添加的产品保留raw_text字段
|
||||
- 价格显示优化:支持多币种、价格区间、单位
|
||||
|
||||
**依赖**:
|
||||
- Python 3 + Flask
|
||||
- Tailwind CSS (CDN)
|
||||
- JSON文件存储
|
||||
- LLM Proxy (http://192.168.2.17:19007/v1)
|
||||
|
||||
---
|
||||
|
||||
@@ -256,7 +272,47 @@ print(response.choices[0].message.content)
|
||||
|
||||
---
|
||||
|
||||
### 7. PDF翻译助手 V1 (pdf-translate-web)
|
||||
### 7. 项目服务管理面板 (project-panel)
|
||||
|
||||
**简介**: 统一管理所有项目和服务,显示运行状态,支持启动、停止、重启控制。
|
||||
|
||||
**目录**: `works/project-panel`
|
||||
|
||||
**启动命令**:
|
||||
```bash
|
||||
cd ~/.openclaw/workspace-coder/works/project-panel
|
||||
python3 app.py
|
||||
```
|
||||
|
||||
**访问地址**: http://localhost:19013
|
||||
|
||||
**检查服务状态**:
|
||||
```bash
|
||||
curl -s http://localhost:19013/api/projects
|
||||
```
|
||||
|
||||
**Git仓库**: http://192.168.2.8:12007/coder/project-panel
|
||||
|
||||
**版本**: v1.0.0
|
||||
|
||||
**功能特点**:
|
||||
- 项目列表展示(Web服务、Cron任务、CLI工具、插件)
|
||||
- 实时状态检测(端口检测、健康检查)
|
||||
- 服务控制(启动、停止、重启)
|
||||
- 日志查看
|
||||
- 类型筛选
|
||||
- 动态添加新项目(API)
|
||||
|
||||
**项目配置**: `projects.json` 文件存储所有项目信息,便于扩展
|
||||
|
||||
**依赖**:
|
||||
- Python 3 + Flask
|
||||
- Tailwind CSS (CDN)
|
||||
- RemixIcon
|
||||
|
||||
---
|
||||
|
||||
### 8. PDF翻译助手 V1 (pdf-translate-web)
|
||||
|
||||
**简介**: 英文PDF翻译中文网站第一版,支持翻译、缓存、用户系统。
|
||||
|
||||
@@ -266,7 +322,7 @@ print(response.choices[0].message.content)
|
||||
|
||||
---
|
||||
|
||||
### 8. PDF翻译脚本 (pdf-translator)
|
||||
### 9. PDF翻译脚本 (pdf-translator)
|
||||
|
||||
**简介**: 基于本地LLM的英文PDF翻译命令行工具,支持Markdown/TXT/JSON输出。
|
||||
|
||||
@@ -284,7 +340,7 @@ python3 translate_pdf.py input.pdf output.md
|
||||
|
||||
---
|
||||
|
||||
### 9. A股历史数据系统 (stock_system)
|
||||
### 10. A股历史数据系统 (stock_system)
|
||||
|
||||
**简介**: 获取所有A股从2010年至今的历史行情数据,支持断点续传。V2版本优化了CPU和磁盘占用。
|
||||
|
||||
@@ -324,7 +380,7 @@ ls -lh /home/xian/.openclaw/common/stock_system/data/stock_daily_data.parquet
|
||||
|
||||
---
|
||||
|
||||
### 10. Web服务监控 (service-monitor)
|
||||
### 11. Web服务监控 (service-monitor)
|
||||
|
||||
**简介**: 自动监控所有Web服务状态,每20分钟检查一次,如有服务停止则发送邮件通知。
|
||||
|
||||
@@ -369,16 +425,146 @@ cat ~/.openclaw/workspace-coder/works/service-monitor/monitor.log
|
||||
|
||||
---
|
||||
|
||||
### 12. A股板块监控 (board-monitor)
|
||||
|
||||
**简介**: 自动获取东方财富板块数据,监控异动并发送邮件通知。
|
||||
|
||||
**目录**: `works/board-monitor`
|
||||
|
||||
**功能特点**:
|
||||
- 行业板块涨跌幅排行
|
||||
- 概念板块涨跌幅排行
|
||||
- 主力资金流入/流出监控
|
||||
- 异动检测(涨跌幅≥3%、资金≥10亿)
|
||||
- HTML格式邮件通知
|
||||
|
||||
**使用命令**:
|
||||
```bash
|
||||
# 测试API连接
|
||||
python3 board_monitor.py test
|
||||
|
||||
# 获取板块数据
|
||||
python3 board_monitor.py get industry --limit 20
|
||||
|
||||
# 执行监控检查
|
||||
python3 board_monitor.py monitor -v
|
||||
```
|
||||
|
||||
**Cron配置**: 交易日盘中每小时检查(10:00-15:00)
|
||||
```
|
||||
0 10,11,13,14,15 * * 1-5 python3 board_monitor.py monitor
|
||||
```
|
||||
|
||||
**Git仓库**: http://192.168.2.8:12007/coder/board-monitor
|
||||
|
||||
**版本**: v1.0.0
|
||||
|
||||
**依赖**:
|
||||
- Python 3 + urllib
|
||||
- 东方财富HTTP API
|
||||
- 邮件发送技能 (email)
|
||||
|
||||
---
|
||||
|
||||
### 12. AI对话系统 V2 (ai-chat-system)
|
||||
|
||||
**简介**: 支持网页端和Matrix端实时同步对话的AI聊天系统,v2.0重构支持大模型池、Agent管理、渠道独立绑定。
|
||||
|
||||
**目录**: `works/ai-chat`
|
||||
|
||||
**启动命令**:
|
||||
```bash
|
||||
cd ~/.openclaw/workspace-coder/works/ai-chat
|
||||
./start_v2.sh
|
||||
```
|
||||
|
||||
**访问地址**:
|
||||
- 网页端: http://localhost:19020
|
||||
- 后台管理: http://localhost:19020/admin
|
||||
|
||||
**检查服务状态**:
|
||||
```bash
|
||||
curl -s http://localhost:19020/api/v2/providers
|
||||
curl -s http://localhost:19020/api/admin/stats
|
||||
```
|
||||
|
||||
**Git仓库**: http://192.168.2.8:12007/coder/ai-chat-system
|
||||
|
||||
**版本**: v2.0.0
|
||||
|
||||
**v2.0.0 新功能**:
|
||||
- **大模型池管理**: 配置多个LLM Provider,Agent可选择使用
|
||||
- **Agent管理**: 每个Agent独立配置系统设定、思考功能开关
|
||||
- **渠道独立绑定**: 网页端和Matrix可绑定不同Agent
|
||||
- **思考功能**: 支持原生思考模型,兼容无思考功能的模型
|
||||
|
||||
**技术栈**:
|
||||
- FastAPI + WebSocket
|
||||
- SQLite (新v2模型: LLMProvider, Agent, Channel)
|
||||
- Matrix Bot (matrix-nio, 支持加密)
|
||||
|
||||
**依赖**:
|
||||
- Python 3 + FastAPI
|
||||
- matrix-nio
|
||||
- 大模型API (可配置多个)
|
||||
|
||||
---
|
||||
|
||||
### 13. 磁盘大文件扫描 (disk-scanner)
|
||||
|
||||
**简介**: 智能扫描Windows/Linux目录,快速定位大文件和大目录,自动跳过零碎文件目录。
|
||||
|
||||
**目录**: `works/disk-scanner`
|
||||
|
||||
**使用命令**:
|
||||
```bash
|
||||
# Windows
|
||||
disk_scanner.bat C:\Users -d 3
|
||||
|
||||
# Linux/macOS
|
||||
python3 disk_scanner.py /home/user -d 3 -s 50M
|
||||
```
|
||||
|
||||
**功能特点**:
|
||||
- 智能跳过零碎目录(node_modules, .git, venv等)
|
||||
- 文件数量阈值判断(超过100文件视为程序包)
|
||||
- 大小阈值过滤(默认10MB以下不深入)
|
||||
- 按大小排序展示
|
||||
- 树形结构清晰展示
|
||||
- 跨平台支持
|
||||
|
||||
**参数**:
|
||||
- `-d/--depth`: 最大扫描深度
|
||||
- `-f/--file-threshold`: 文件数阈值(默认100)
|
||||
- `-s/--size-threshold`: 大小阈值(默认10M)
|
||||
|
||||
**Git仓库**: http://192.168.2.8:12007/coder/disk-scanner
|
||||
|
||||
**版本**: v1.0.0
|
||||
|
||||
**依赖**:
|
||||
- Python 3.6+(仅标准库,无需额外安装)
|
||||
|
||||
---
|
||||
|
||||
## 端口分配表
|
||||
|
||||
| 端口 | 项目 | 说明 |
|
||||
|------|------|------|
|
||||
| 19000 | PDF翻译助手 V2 | 主服务 + 后台 |
|
||||
| 19001 | LLM Index RAG | API服务 |
|
||||
| 19002-19006 | 预留 | 待分配 |
|
||||
| 19007 | LLM Proxy | API服务 |
|
||||
| 19008 | LLM Proxy | 后台管理 |
|
||||
| 19009 | 碎片信息记录 | Web服务 |
|
||||
| 19010 | ParamHub Python | Web服务 |
|
||||
| 19002-19008 | 预留 | 待分配 |
|
||||
| 19011-19100 | 预留 | 待分配 |
|
||||
| 19011 | 产品参数爬取 | API服务 |
|
||||
| 19012 | 产品参数爬取 | 后台管理 |
|
||||
| 19013 | 项目服务管理面板 | Web服务 |
|
||||
| 19014 | Xian Favor | 收藏系统 |
|
||||
| 19015 | 多智能体竞标调度 | Web服务 |
|
||||
| 19020 | AI对话系统 V2 | 主服务 + Matrix Bot |
|
||||
| 19021-19100 | 预留 | 待分配 |
|
||||
|
||||
**端口规范**: 所有Web服务必须使用 19000-19100 范围内的端口!
|
||||
|
||||
@@ -393,9 +579,14 @@ cat ~/.openclaw/workspace-coder/works/service-monitor/monitor.log
|
||||
| LLM Index RAG | http://192.168.2.8:12007/coder/llm-index-rag | v1.2.0 |
|
||||
| LLM Proxy | http://192.168.2.8:12007/coder/llm-proxy | v0.5.1 |
|
||||
| 产品参数爬取系统 | http://192.168.2.8:12007/coder/product-crawler | v1.0.0 |
|
||||
| 项目服务管理面板 | http://192.168.2.8:12007/coder/project-panel | v1.0.0 |
|
||||
| 网页助手插件 | http://192.168.2.8:12007/coder/web-context-extension | v0.1.0 |
|
||||
| A股历史数据系统 | http://192.168.2.8:12007/coder/stock_system | v0.2.0 |
|
||||
| Web服务监控 | http://192.168.2.8:12007/coder/service-monitor | v1.0.0 |
|
||||
| 邮件收发技能 | http://192.168.2.8:12007/coder/skill-email | v1.1.0 |
|
||||
| A股板块监控 | http://192.168.2.8:12007/coder/board-monitor | v1.0.0 |
|
||||
| AI对话系统 V2 | http://192.168.2.8:12007/coder/ai-chat-system | v2.0.0 |
|
||||
| 磁盘大文件扫描 | http://192.168.2.8:12007/coder/disk-scanner | v1.0.0 |
|
||||
|
||||
**Git服务器**: http://192.168.2.8:12007/
|
||||
**账号**: coder / Hps123@!
|
||||
@@ -440,6 +631,54 @@ pkill -f "app.py.*port=19010"
|
||||
- 配置 Cron 定时任务(每20分钟检查)
|
||||
- 邮件通知功能(发送到 zuitoushang@tphai.com)
|
||||
|
||||
### 2026-04-11
|
||||
- 创建项目服务管理面板 (project-panel)
|
||||
- 端口: 19013
|
||||
- 功能: 项目列表、状态检测、启动/停止/重启控制、日志查看
|
||||
- Git仓库: http://192.168.2.8:12007/coder/project-panel v1.0.0
|
||||
|
||||
### 2026-04-09
|
||||
- 创建 PROJECTS.md 项目记录文件
|
||||
- 记录现有8个项目详情
|
||||
- 整理端口分配表和快速操作命令
|
||||
- 优化 stock_system 获取脚本 V2(分文件+批量合并+SQLite)
|
||||
|
||||
### 待办
|
||||
- [ ] 为每个项目创建 Git 仓库和版本 tag
|
||||
- [ ] 配置 systemd 服务实现开机自启动
|
||||
|
||||
### 2026-04-12
|
||||
- 技术论坛 v1.1.0 安全重构
|
||||
- 后台添加登录验证(Session + JWT)
|
||||
- JSON存储改为SQLite数据库
|
||||
- API密钥移至配置文件(支持环境变量)
|
||||
- SECRET_KEY改为随机生成
|
||||
- 新增管理员登录页面
|
||||
- Git仓库: http://192.168.2.8:12007/coder/tech-forumclaw/workspace-coder/works/param-hub-python && nohup python3 app.py > /tmp/paramhub.log 2>&1 &
|
||||
```
|
||||
|
||||
### 停止所有Web服务
|
||||
```bash
|
||||
pkill -f "app.py.*port=19000"
|
||||
pkill -f "app.py.*port=19009"
|
||||
pkill -f "app.py.*port=19010"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 更新日志
|
||||
|
||||
### 2026-04-10
|
||||
- 创建 Web服务监控系统
|
||||
- 配置 Cron 定时任务(每20分钟检查)
|
||||
- 邮件通知功能(发送到 zuitoushang@tphai.com)
|
||||
|
||||
### 2026-04-11
|
||||
- 创建项目服务管理面板 (project-panel)
|
||||
- 端口: 19013
|
||||
- 功能: 项目列表、状态检测、启动/停止/重启控制、日志查看
|
||||
- Git仓库: http://192.168.2.8:12007/coder/project-panel v1.0.0
|
||||
|
||||
### 2026-04-09
|
||||
- 创建 PROJECTS.md 项目记录文件
|
||||
- 记录现有8个项目详情
|
||||
|
||||
@@ -74,7 +74,13 @@ curl -X POST "http://coder:Hps123%40%21@192.168.2.8:12007/api/v1/user/repos" \
|
||||
| 项目 | 端口 |
|
||||
|------|------|
|
||||
| 文章工作流后台 | 19001 |
|
||||
| (预留) | 19002-19100 |
|
||||
| 方言AI主服务 | 19002 |
|
||||
| 方言AI后台管理 | 19003 |
|
||||
| 技术论坛 | 19004 |
|
||||
| 参数百科前台 | 3000 |
|
||||
| 参数百科后台 | 19006 |
|
||||
| 大模型API中转 | /coder/llm-proxy | 19007/19008 | v0.2.0 |
|
||||
| 预留 | 19008-19100 |
|
||||
|
||||
---
|
||||
|
||||
@@ -99,11 +105,18 @@ curl -X POST "http://coder:Hps123%40%21@192.168.2.8:12007/api/v1/user/repos" \
|
||||
|
||||
### 4. 方言版AI对话助手 (dialect-chat)
|
||||
- 仓库: http://192.168.2.8:12007/coder/dialect-chat
|
||||
- 版本: v0.1.0
|
||||
- 版本: v0.2.0
|
||||
- 技术: Python + Flask + 原生JS
|
||||
- 访问地址: http://localhost:19002
|
||||
- 访问地址: http://localhost:19002 (主服务) / http://localhost:19003 (后台)
|
||||
- 功能: 8种方言、语音识别、用户系统
|
||||
|
||||
### 5. 技术论坛与技术分享网站 (tech-forum)
|
||||
- 仓库: http://192.168.2.8:12007/coder/tech-forum
|
||||
- 版本: v0.1.0
|
||||
- 技术: Python + Flask + Tailwind CSS
|
||||
- 访问地址: http://localhost:19004
|
||||
- 功能: 技术交流帖子、工具分享主题、用户系统
|
||||
|
||||
---
|
||||
|
||||
## 待办事项
|
||||
@@ -111,4 +124,13 @@ curl -X POST "http://coder:Hps123%40%21@192.168.2.8:12007/api/v1/user/repos" \
|
||||
- [ ] param-hub 后续功能迭代
|
||||
- [ ] 添加更多模型数据
|
||||
- [ ] 添加更多GPU数据
|
||||
- [ ] 实现数据库持久化
|
||||
- [ ] 实现数据库持久化<EFBFBD><EFBFBD>数据库持久化<EFBFBD><EFBFBD>迭代
|
||||
- [ ] 添加更多模型数据
|
||||
- [ ] 添加更多GPU数据
|
||||
- [ ] 实现数据库持久化<E4B985><E58C96>数据库持久化续功能迭代
|
||||
- [ ] 添加更多模型数据
|
||||
- [ ] 添加更多GPU数据
|
||||
- [ ] 实现数据库持久化<E4B985><E58C96>数据库持久化<E4B985><E58C96>迭代
|
||||
- [ ] 添加更多模型数据
|
||||
- [ ] 添加更多GPU数据
|
||||
- [ ] 实现数据库持久化<E4B985><E58C96>数据库持久化
|
||||
79
memory/2026-04-10.md
Normal file
79
memory/2026-04-10.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# 2026-04-10
|
||||
|
||||
## 完成的工作
|
||||
|
||||
### 邮件收件箱管理
|
||||
|
||||
- 创建 `works/mailbox/` 邮件管理系统
|
||||
- 支持:同步、存储、状态追踪、归档
|
||||
- 状态流转:unread → read → pending → processing → done → archived
|
||||
- 同步邮件 [1]:A股板块分析方案汇总 → 已完成(board_monitor已实现)
|
||||
|
||||
### A股板块监控系统
|
||||
|
||||
- 创建 `works/board-monitor/board_monitor.py`
|
||||
- 东方财富HTTP API数据获取(解决代理问题)
|
||||
- **改为盘后报告模式**:每个交易日17:00发送
|
||||
- **邮件结构**:正文分析总结 + 附件详细CSV数据
|
||||
- **历史数据分析**(v1.3.0新增):
|
||||
- SQLite数据库存储每日数据
|
||||
- 连续上涨/下跌板块统计
|
||||
- 板块轮动分析
|
||||
- 近5日资金流向趋势
|
||||
- 收件人: wlq@tphai.com
|
||||
- 推送到仓库: http://192.168.2.8:12007/coder/board-monitor v1.3.0
|
||||
|
||||
### 邮件技能扩展
|
||||
|
||||
- 新增 IMAP 邮件接收功能 (`scripts/receive_email.py`)
|
||||
- 支持查看未读邮件列表
|
||||
- 支持读取邮件详情和正文
|
||||
- 支持自动保存附件
|
||||
- 支持读取文本附件内容(.txt, .md, .json, .csv, .py 等)
|
||||
- 重命名技能目录: email-sender → email
|
||||
- 推送到仓库: http://192.168.2.8:12007/coder/skill-email v1.1.0
|
||||
|
||||
### 命令示例
|
||||
|
||||
```bash
|
||||
# 查看未读邮件
|
||||
python3 receive_email.py unread
|
||||
|
||||
# 读取邮件详情
|
||||
python3 receive_email.py read <邮件ID>
|
||||
|
||||
# 查看附件内容
|
||||
python3 receive_email.py attachment <邮件ID>
|
||||
```
|
||||
|
||||
### Web服务监控系统
|
||||
|
||||
- 创建 `works/service-monitor/monitor.py`
|
||||
- 监控8个Web服务端口:
|
||||
- PDF翻译助手 V2 (19000)
|
||||
- LLM Index RAG (19001)
|
||||
- 碎片信息记录 (19009)
|
||||
- ParamHub Python (19010)
|
||||
- 产品参数爬取 API/后台 (19011/19012)
|
||||
- LLM Proxy API/后台 (19007/19008)
|
||||
- Cron定时任务:每20分钟检查一次
|
||||
- 邮件通知:zuitoushang@tphai.com
|
||||
- 发现停止服务时自动发送HTML格式邮件,包含启动命令
|
||||
|
||||
### Cron配置
|
||||
|
||||
```
|
||||
*/20 * * * * /usr/bin/python3 /home/xian/.openclaw/workspace-coder/works/service-monitor/monitor.py
|
||||
```
|
||||
|
||||
## 服务状态
|
||||
|
||||
当前运行中:
|
||||
- ✅ LLM Index RAG (19001)
|
||||
- ✅ 碎片信息记录 (19009)
|
||||
- ✅ ParamHub Python (19010)
|
||||
- ✅ 产品参数爬取 API/后台 (19011/19012)
|
||||
- ✅ LLM Proxy API/后台 (19007/19008)
|
||||
|
||||
已停止:
|
||||
- ❌ PDF翻译助手 V2 (19000)
|
||||
72
memory/2026-04-11.md
Normal file
72
memory/2026-04-11.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# 2026-04-11
|
||||
|
||||
## 完成的工作
|
||||
|
||||
### PDF翻译助手 V2 v2.1.0
|
||||
|
||||
**新功能:系统配置动态管理**
|
||||
|
||||
- **用户类型配置**:
|
||||
- 支持添加新的用户类型(自定义标识、显示名称)
|
||||
- 支持编辑权限:每日翻译次数、最大页数、文件大小
|
||||
- 支持选择功能权限列表
|
||||
- 支持删除自定义类型(系统类型不可删除)
|
||||
- 支持启用/禁用用户类型
|
||||
|
||||
- **会员套餐配置**:
|
||||
- 支持添加新的会员套餐(自定义标识、显示名称)
|
||||
- 支持编辑价格、原价、周期
|
||||
- 支持设置购买后升级的用户类型
|
||||
- 支持上架/下架套餐
|
||||
- 支持设置推荐套餐
|
||||
- 支持删除自定义套餐(系统套餐不可删除)
|
||||
|
||||
- **新增数据模型**:
|
||||
- `UserTypeConfig`:用户类型配置表
|
||||
- `MembershipPlanConfig`:会员套餐配置表
|
||||
|
||||
- **新增页面**:
|
||||
- `user_types.html`:用户类型配置列表
|
||||
- `user_type_form.html`:添加/编辑用户类型表单
|
||||
- `membership_plans.html`:会员套餐配置列表
|
||||
- `membership_plan_form.html`:添加/编辑会员套餐表单
|
||||
|
||||
- **改进settings页面**:提供配置入口链接
|
||||
|
||||
**Git仓库**: http://192.168.2.8:12007/coder/pdf-translate-web
|
||||
**版本**: v2.1.0
|
||||
|
||||
### ParamHub Python v1.1.0
|
||||
|
||||
**新功能:**
|
||||
- 智能添加:粘贴文本自动解析为结构化数据(大模型API)
|
||||
- 展示开关:各分类和产品支持显示/隐藏控制(默认显示)
|
||||
- 原始数据保留:智能添加的产品保留raw_text字段
|
||||
|
||||
**优化:**
|
||||
- 价格显示优化:支持多币种(USD/CNY/EUR)、价格区间、单位
|
||||
- CPU图标修复:改为ri-cpu-line
|
||||
- favicon添加:所有页面增加浏览器标签图标
|
||||
|
||||
**Git仓库**: http://192.168.2.8:12007/coder/param-hub-python
|
||||
**版本**: v1.1.0
|
||||
|
||||
### 碎片信息记录项目优化
|
||||
|
||||
- 更换大模型接口:改用LLM Proxy (http://192.168.2.17:19007/v1)
|
||||
- 添加Ctrl+S快捷键保存功能(阻止浏览器默认保存)
|
||||
- 添加favicon浏览器标签图标
|
||||
|
||||
### 项目服务管理面板 v1.0.0
|
||||
|
||||
- 创建 `works/project-panel/` 目录结构
|
||||
- 端口: 19013
|
||||
- 功能:
|
||||
- 项目列表展示(Web服务、Cron任务、CLI工具、插件)
|
||||
- 实时状态检测(端口检测、健康检查)
|
||||
- 服务控制(启动、停止、重启)
|
||||
- 日志查看
|
||||
- 类型筛选
|
||||
- 动态添加新项目(API)
|
||||
- 配置文件: `projects.json` 存储项目信息,便于扩展
|
||||
- Git仓库: http://192.168.2.8:12007/coder/project-panel v1.0.0
|
||||
87
memory/2026-04-12.md
Normal file
87
memory/2026-04-12.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# 2026-04-12
|
||||
|
||||
## 完成的工作
|
||||
|
||||
### Xian Favor 收藏系统 v1.0.0
|
||||
|
||||
创建了一个完整的收藏管理系统,支持三种操作模式:
|
||||
|
||||
**功能特性:**
|
||||
- 多种内容类型:文本笔记、链接收藏、专栏订阅、待办事项
|
||||
- 标签系统:灵活分类,支持多标签关联
|
||||
- 状态管理:待办支持待处理/进行中/已完成三种状态
|
||||
- 优先级:低/中/高/紧急四个级别
|
||||
- 截止日期:待办事项支持设置截止日期
|
||||
- 快速搜索:全文搜索标题、内容、备注
|
||||
- 统计面板:实时统计各类型、状态数量
|
||||
|
||||
**三种操作模式:**
|
||||
|
||||
1. **命令行 (CLI)**
|
||||
- `xian_favor add text/link/column/todo` - 添加各类内容
|
||||
- `xian_favor list` - 列出条目(支持类型、状态、标签筛选)
|
||||
- `xian_favor show` - 查看详情
|
||||
- `xian_favor edit` - 编辑条目
|
||||
- `xian_favor done` - 完成待办(快捷命令)
|
||||
- `xian_favor delete` - 删除条目
|
||||
- `xian_favor search` - 搜索关键词
|
||||
- `xian_favor tags` - 标签管理
|
||||
- `xian_favor stats` - 统计信息
|
||||
- `xian_favor serve` - 启动API服务
|
||||
|
||||
2. **API服务 (端口 19014)**
|
||||
- `/api/items` - CRUD操作
|
||||
- `/api/items/<id>/done` - 完成待办
|
||||
- `/api/tags` - 标签管理
|
||||
- `/api/stats` - 统计信息
|
||||
- `/api/search` - 搜索
|
||||
|
||||
3. **Web界面**
|
||||
- 侧边栏快速筛选(类型、状态)
|
||||
- 实时搜索
|
||||
- 统计卡片
|
||||
- 添加/编辑/删除操作
|
||||
- 一键完成待办
|
||||
|
||||
**技术实现:**
|
||||
- 数据库:SQLite + WAL模式(提高并发性能)
|
||||
- 存储:`~/.xian_favor/xian_favor.db`
|
||||
- 后端:Flask + Flask-CORS
|
||||
- 前端:Bootstrap 5 + 原生JavaScript
|
||||
|
||||
**解决的问题:**
|
||||
- SQLite并发锁问题:WAL模式 + busy_timeout + 惰性初始化
|
||||
- 嵌套连接问题:_add_tags_to_item使用同一个连接而非调用create_tag
|
||||
- 路径问题:使用Path.home()而非~字符串
|
||||
|
||||
**Git仓库**: http://192.168.2.8:12007/coder/xian-favor
|
||||
**版本**: v1.0.0
|
||||
|
||||
---
|
||||
|
||||
### AI对话系统 - 后台大模型配置优化
|
||||
|
||||
优化了ai-chat-system项目的后台管理界面,增加专门的AI模型配置功能:
|
||||
|
||||
**新增功能:**
|
||||
- 🧠 AI配置专用标签页(默认显示)
|
||||
- API地址输入框
|
||||
- API密钥输入框
|
||||
- 模型选择:支持下拉选择和手动输入两种方式(datalist + input)
|
||||
- 保存配置按钮
|
||||
- 测试连接按钮(验证API是否正常)
|
||||
- 刷新模型列表按钮(从API获取可用模型)
|
||||
- 实时状态显示(连接状态、Mock模式指示)
|
||||
|
||||
**新增API端点:**
|
||||
- `/api/admin/ai-config` GET/POST - 获取/更新AI配置
|
||||
- `/api/admin/models` GET - 获取可用模型列表(从API或默认列表)
|
||||
- `/api/admin/test-ai` POST - 测试AI连接
|
||||
|
||||
**修复的Bug:**
|
||||
- 测试连接显示"undefined"错误:改为从数据库读取最新配置,而非依赖ai_service属性
|
||||
- 添加详细错误提示:连接失败、超时、无法连接等具体原因
|
||||
|
||||
**项目目录**: `works/ai-chat`
|
||||
**端口**: 19020
|
||||
**后台管理**: http://localhost:19020/admin
|
||||
1
skills/email
Submodule
1
skills/email
Submodule
Submodule skills/email added at 3c0cb213c9
@@ -1,168 +0,0 @@
|
||||
---
|
||||
name: email-sender
|
||||
description: Send emails via SMTP with support for attachments, CC/BCC, HTML content, and multiple SMTP accounts. Use when user wants to send emails through Python/SMTP, configure email settings, or send emails with attachments.
|
||||
---
|
||||
|
||||
# Email Sender / 邮件发送工具
|
||||
|
||||
通过 SMTP 发送邮件,支持附件、抄送/密送、HTML 格式和多账号管理。
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 配置 SMTP
|
||||
|
||||
```bash
|
||||
cd ~/.openclaw/workspace-coder/skills/email-sender/scripts
|
||||
python3 send_email.py config my-email \
|
||||
--server mail.tphai.com \
|
||||
--port 587 \
|
||||
--email guwen@tphai.com \
|
||||
--password "your-password" \
|
||||
--no-tls
|
||||
```
|
||||
|
||||
参数说明:
|
||||
- `my-email`: 配置名称(可自定义)
|
||||
- `--server`: SMTP 服务器地址
|
||||
- `--port`: SMTP 端口
|
||||
- `--email`: 邮箱地址
|
||||
- `--password`: 邮箱密码
|
||||
- `--no-tls`: 不使用 TLS 加密(默认使用 TLS)
|
||||
|
||||
### 2. 查看配置
|
||||
|
||||
```bash
|
||||
python3 send_email.py list
|
||||
```
|
||||
|
||||
### 3. 发送邮件
|
||||
|
||||
**简单邮件:**
|
||||
```bash
|
||||
python3 send_email.py send \
|
||||
--to wlq@tphai.com \
|
||||
--subject "测试邮件" \
|
||||
--body "这是一封测试邮件"
|
||||
```
|
||||
|
||||
**带附件的邮件:**
|
||||
```bash
|
||||
python3 send_email.py send \
|
||||
--to wlq@tphai.com \
|
||||
--subject "带附件的邮件" \
|
||||
--body "请查收附件" \
|
||||
--attach /path/to/file1.pdf \
|
||||
--attach /path/to/file2.jpg
|
||||
```
|
||||
|
||||
**HTML 邮件:**
|
||||
```bash
|
||||
python3 send_email.py send \
|
||||
--to wlq@tphai.com \
|
||||
--subject "HTML 邮件" \
|
||||
--body "<h1>标题</h1><p>内容</p>" \
|
||||
--html
|
||||
```
|
||||
|
||||
**抄送和密送:**
|
||||
```bash
|
||||
python3 send_email.py send \
|
||||
--to wlq@tphai.com \
|
||||
--cc "cc1@example.com,cc2@example.com" \
|
||||
--bcc "bcc@example.com" \
|
||||
--subject "抄送测试" \
|
||||
--body "这是一封抄送测试邮件"
|
||||
```
|
||||
|
||||
## Python API 使用
|
||||
|
||||
```python
|
||||
from send_email import send_email, setup_account
|
||||
|
||||
# 配置 SMTP
|
||||
setup_account(
|
||||
name="work",
|
||||
smtp_server="mail.tphai.com",
|
||||
smtp_port=587,
|
||||
email="guwen@tphai.com",
|
||||
password="your-password",
|
||||
use_tls=False
|
||||
)
|
||||
|
||||
# 发送简单邮件
|
||||
send_email(
|
||||
to="wlq@tphai.com",
|
||||
subject="测试",
|
||||
body="内容"
|
||||
)
|
||||
|
||||
# 发送带附件的邮件
|
||||
send_email(
|
||||
to="wlq@tphai.com",
|
||||
subject="附件测试",
|
||||
body="请查收附件",
|
||||
attachments=["/path/to/file.pdf", "/path/to/image.jpg"],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# 发送 HTML 邮件
|
||||
send_email(
|
||||
to="wlq@tphai.com",
|
||||
subject="HTML 测试",
|
||||
body="<h1>Hello</h1><p>World</p>",
|
||||
html=True
|
||||
)
|
||||
|
||||
# 使用特定账号
|
||||
send_email(
|
||||
to="wlq@tphai.com",
|
||||
subject="使用指定账号",
|
||||
body="内容",
|
||||
account_name="work"
|
||||
)
|
||||
```
|
||||
|
||||
## 配置文件
|
||||
|
||||
配置保存在 `scripts/smtp_config.json` 中:
|
||||
|
||||
```json
|
||||
{
|
||||
"accounts": [
|
||||
{
|
||||
"name": "my-email",
|
||||
"smtp_server": "mail.tphai.com",
|
||||
"smtp_port": 587,
|
||||
"email": "guwen@tphai.com",
|
||||
"password": "your-password",
|
||||
"use_tls": false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 常用 SMTP 设置
|
||||
|
||||
| 服务商 | SMTP 服务器 | 端口 | TLS |
|
||||
|--------|-------------|------|-----|
|
||||
| Gmail | smtp.gmail.com | 587 | 是 |
|
||||
| Outlook | smtp.office365.com | 587 | 是 |
|
||||
| QQ邮箱 | smtp.qq.com | 587 | 是 |
|
||||
| 163邮箱 | smtp.163.com | 465 | 是 |
|
||||
| 企业邮箱 | mail.tphai.com | 587 | 否 |
|
||||
|
||||
## 故障排除
|
||||
|
||||
**认证失败:**
|
||||
- 检查邮箱密码是否正确
|
||||
- Gmail 需要使用「应用专用密码」而非登录密码
|
||||
- QQ邮箱需要使用授权码而非登录密码
|
||||
|
||||
**连接失败:**
|
||||
- 检查 SMTP 服务器地址和端口
|
||||
- 检查防火墙设置
|
||||
- 尝试切换 TLS/SSL 模式
|
||||
|
||||
**邮件被退回:**
|
||||
- 检查收件人地址是否正确
|
||||
- 检查邮件头是否完整(本工具自动添加 Date 和 Message-Id)
|
||||
2
skills/email-sender/scripts/.gitignore
vendored
2
skills/email-sender/scripts/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
# SMTP配置文件(包含密码)
|
||||
smtp_config.json
|
||||
@@ -1,293 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
邮件发送脚本
|
||||
支持纯文字/HTML 邮件、抄送/密送、附件和批量发送
|
||||
"""
|
||||
|
||||
import smtplib
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.application import MIMEApplication
|
||||
from email.utils import formatdate, make_msgid
|
||||
from typing import List, Optional
|
||||
|
||||
# 配置文件路径
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
CONFIG_FILE = os.path.join(SCRIPT_DIR, "smtp_config.json")
|
||||
|
||||
|
||||
def load_config() -> dict:
|
||||
"""加载 SMTP 配置"""
|
||||
if not os.path.exists(CONFIG_FILE):
|
||||
return {"accounts": []}
|
||||
|
||||
with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def save_config(config: dict):
|
||||
"""保存 SMTP 配置"""
|
||||
with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
|
||||
json.dump(config, f, indent=2, ensure_ascii=False)
|
||||
|
||||
|
||||
def setup_account(
|
||||
name: str,
|
||||
smtp_server: str,
|
||||
smtp_port: int,
|
||||
email: str,
|
||||
password: str,
|
||||
use_tls: bool = True
|
||||
):
|
||||
"""配置 SMTP 账号"""
|
||||
config = load_config()
|
||||
|
||||
# 检查是否已存在同名配置
|
||||
for i, acc in enumerate(config["accounts"]):
|
||||
if acc["name"] == name:
|
||||
print(f"配置 '{name}' 已存在,正在更新...")
|
||||
config["accounts"][i] = {
|
||||
"name": name,
|
||||
"smtp_server": smtp_server,
|
||||
"smtp_port": smtp_port,
|
||||
"email": email,
|
||||
"password": password, # 明文存储,仅用于本地
|
||||
"use_tls": use_tls
|
||||
}
|
||||
save_config(config)
|
||||
return
|
||||
|
||||
# 添加新配置
|
||||
config["accounts"].append({
|
||||
"name": name,
|
||||
"smtp_server": smtp_server,
|
||||
"smtp_port": smtp_port,
|
||||
"email": email,
|
||||
"password": password,
|
||||
"use_tls": use_tls
|
||||
})
|
||||
save_config(config)
|
||||
print(f"✅ 配置 '{name}' 已保存")
|
||||
|
||||
|
||||
def list_accounts():
|
||||
"""列出所有 SMTP 配置"""
|
||||
config = load_config()
|
||||
|
||||
if not config["accounts"]:
|
||||
print("暂无 SMTP 配置")
|
||||
return
|
||||
|
||||
print("\n=== SMTP 配置列表 ===")
|
||||
for i, acc in enumerate(config["accounts"], 1):
|
||||
print(f"\n{i}. {acc['name']}")
|
||||
print(f" 服务器: {acc['smtp_server']}:{acc['smtp_port']}")
|
||||
print(f" 邮箱: {acc['email']}")
|
||||
print(f" TLS: {'是' if acc['use_tls'] else '否'}")
|
||||
|
||||
|
||||
def get_account(name: Optional[str] = None) -> Optional[dict]:
|
||||
"""获取 SMTP 配置"""
|
||||
config = load_config()
|
||||
|
||||
if not config["accounts"]:
|
||||
return None
|
||||
|
||||
if name is None:
|
||||
return config["accounts"][0]
|
||||
|
||||
for acc in config["accounts"]:
|
||||
if acc["name"] == name:
|
||||
return acc
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def send_email(
|
||||
to: str,
|
||||
subject: str,
|
||||
body: str,
|
||||
account_name: Optional[str] = None,
|
||||
html: bool = False,
|
||||
cc: Optional[str] = None,
|
||||
bcc: Optional[str] = None,
|
||||
from_name: Optional[str] = None,
|
||||
attachments: Optional[List[str]] = None,
|
||||
verbose: bool = False
|
||||
) -> bool:
|
||||
"""
|
||||
发送邮件
|
||||
|
||||
参数:
|
||||
to: 收件人邮箱地址
|
||||
subject: 邮件主题
|
||||
body: 邮件内容
|
||||
account_name: SMTP 配置名称(可选,默认使用第一个)
|
||||
html: 是否为 HTML 邮件(默认 False)
|
||||
cc: 抄送邮箱地址,多个用逗号分隔(可选)
|
||||
bcc: 密送邮箱地址,多个用逗号分隔(可选)
|
||||
from_name: 发件人显示名称(可选)
|
||||
attachments: 附件文件路径列表(可选)
|
||||
verbose: 是否显示详细日志(默认 False)
|
||||
|
||||
返回:
|
||||
bool: 发送成功返回 True,失败返回 False
|
||||
"""
|
||||
try:
|
||||
# 获取 SMTP 配置
|
||||
account = get_account(account_name)
|
||||
if account is None:
|
||||
print("❌ 错误:未找到 SMTP 配置,请先运行配置")
|
||||
return False
|
||||
|
||||
# 创建邮件
|
||||
if attachments:
|
||||
msg = MIMEMultipart()
|
||||
msg.attach(MIMEText(body, "html" if html else "plain", "utf-8"))
|
||||
else:
|
||||
msg = MIMEText(body, "html" if html else "plain", "utf-8")
|
||||
|
||||
# 设置邮件头
|
||||
msg["Subject"] = subject
|
||||
msg["From"] = f"{from_name} <{account['email']}>" if from_name else account["email"]
|
||||
msg["To"] = to
|
||||
msg["Date"] = formatdate(localtime=True)
|
||||
msg["Message-Id"] = make_msgid(domain=account["email"].split("@")[1])
|
||||
|
||||
if cc:
|
||||
msg["Cc"] = cc
|
||||
|
||||
# 添加附件
|
||||
if attachments:
|
||||
for file_path in attachments:
|
||||
if not os.path.exists(file_path):
|
||||
print(f"⚠️ 附件不存在,已跳过: {file_path}")
|
||||
continue
|
||||
|
||||
with open(file_path, "rb") as f:
|
||||
part = MIMEApplication(f.read())
|
||||
|
||||
filename = os.path.basename(file_path)
|
||||
part.add_header(
|
||||
"Content-Disposition",
|
||||
"attachment",
|
||||
filename=filename
|
||||
)
|
||||
msg.attach(part)
|
||||
if verbose:
|
||||
print(f"📎 已添加附件: {filename}")
|
||||
|
||||
# 连接 SMTP 服务器
|
||||
if verbose:
|
||||
print(f"📡 正在连接 {account['smtp_server']}:{account['smtp_port']}...")
|
||||
|
||||
if account["use_tls"]:
|
||||
server = smtplib.SMTP(account["smtp_server"], account["smtp_port"])
|
||||
server.starttls()
|
||||
else:
|
||||
server = smtplib.SMTP(account["smtp_server"], account["smtp_port"])
|
||||
|
||||
# 登录
|
||||
if verbose:
|
||||
print(f"🔑 正在登录 {account['email']}...")
|
||||
server.login(account["email"], account["password"])
|
||||
|
||||
# 准备收件人列表
|
||||
recipients = [to]
|
||||
if cc:
|
||||
recipients.extend([addr.strip() for addr in cc.split(",")])
|
||||
if bcc:
|
||||
recipients.extend([addr.strip() for addr in bcc.split(",")])
|
||||
|
||||
# 发送邮件
|
||||
if verbose:
|
||||
print(f"📤 正在发送邮件...")
|
||||
server.sendmail(account["email"], recipients, msg.as_string())
|
||||
server.quit()
|
||||
|
||||
print(f"✅ 邮件发送成功")
|
||||
print(f" 收件人: {to}")
|
||||
if cc:
|
||||
print(f" 抄送: {cc}")
|
||||
if attachments:
|
||||
valid_attachments = [a for a in attachments if os.path.exists(a)]
|
||||
print(f" 附件: {len(valid_attachments)} 个")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 邮件发送失败: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""命令行入口"""
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description="邮件发送工具")
|
||||
subparsers = parser.add_subparsers(dest="command", help="可用命令")
|
||||
|
||||
# 配置命令
|
||||
config_parser = subparsers.add_parser("config", help="配置 SMTP")
|
||||
config_parser.add_argument("name", help="配置名称")
|
||||
config_parser.add_argument("--server", required=True, help="SMTP 服务器地址")
|
||||
config_parser.add_argument("--port", type=int, required=True, help="SMTP 端口")
|
||||
config_parser.add_argument("--email", required=True, help="邮箱地址")
|
||||
config_parser.add_argument("--password", required=True, help="邮箱密码")
|
||||
config_parser.add_argument("--no-tls", action="store_true", help="不使用 TLS(默认使用)")
|
||||
|
||||
# 列出配置命令
|
||||
subparsers.add_parser("list", help="列出所有配置")
|
||||
|
||||
# 发送命令
|
||||
send_parser = subparsers.add_parser("send", help="发送邮件")
|
||||
send_parser.add_argument("--to", "-t", required=True, help="收件人邮箱")
|
||||
send_parser.add_argument("--subject", "-s", required=True, help="邮件主题")
|
||||
send_parser.add_argument("--body", "-b", required=True, help="邮件内容")
|
||||
send_parser.add_argument("--account", "-a", help="使用指定配置")
|
||||
send_parser.add_argument("--html", action="store_true", help="HTML 格式")
|
||||
send_parser.add_argument("--cc", help="抄送邮箱(多个用逗号分隔)")
|
||||
send_parser.add_argument("--bcc", help="密送邮箱(多个用逗号分隔)")
|
||||
send_parser.add_argument("--from-name", help="发件人显示名称")
|
||||
send_parser.add_argument("--attach", "-f", action="append", help="附件文件路径(可多次使用)")
|
||||
send_parser.add_argument("-v", "--verbose", action="store_true", help="显示详细日志")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == "config":
|
||||
setup_account(
|
||||
name=args.name,
|
||||
smtp_server=args.server,
|
||||
smtp_port=args.port,
|
||||
email=args.email,
|
||||
password=args.password,
|
||||
use_tls=not args.no_tls
|
||||
)
|
||||
|
||||
elif args.command == "list":
|
||||
list_accounts()
|
||||
|
||||
elif args.command == "send":
|
||||
success = send_email(
|
||||
to=args.to,
|
||||
subject=args.subject,
|
||||
body=args.body,
|
||||
account_name=args.account,
|
||||
html=args.html,
|
||||
cc=args.cc,
|
||||
bcc=args.bcc,
|
||||
from_name=args.from_name,
|
||||
attachments=args.attach,
|
||||
verbose=args.verbose
|
||||
)
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
1
works/ai-chat
Submodule
1
works/ai-chat
Submodule
Submodule works/ai-chat added at 90d31dba69
1
works/board-monitor
Submodule
1
works/board-monitor
Submodule
Submodule works/board-monitor added at 8d77c4a852
1
works/disk-scanner
Submodule
1
works/disk-scanner
Submodule
Submodule works/disk-scanner added at 4ce1c93ad3
Submodule works/llm-index-rag updated: 4fb4d61877...ab6469b9dd
77
works/mailbox/README.md
Normal file
77
works/mailbox/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# 邮件收件箱管理
|
||||
|
||||
管理已读邮件内容和处理状态。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
mailbox/
|
||||
├── inbox.json # 收件箱状态索引
|
||||
├── mailbox_manager.py # 管理脚本
|
||||
├── emails/ # 邮件存储目录
|
||||
│ └── <邮件ID>/
|
||||
│ ├── meta.json # 邮件元数据(主题、发件人、状态等)
|
||||
│ ├── body.txt # 邮件正文
|
||||
│ └── attachments/ # 附件目录
|
||||
└── archive/ # 已归档邮件
|
||||
```
|
||||
|
||||
## 邮件状态
|
||||
|
||||
| 状态 | 说明 | 命令 |
|
||||
|------|------|------|
|
||||
| unread | 未读 | sync |
|
||||
| read | 已读 | read |
|
||||
| pending | 待处理 | pending |
|
||||
| processing | 处理中 | processing |
|
||||
| done | 已完成 | done |
|
||||
| archived | 已归档 | archive |
|
||||
|
||||
## 使用方法
|
||||
|
||||
```bash
|
||||
cd /home/xian/.openclaw/workspace-coder/works/mailbox
|
||||
|
||||
# 从 IMAP 同步未读邮件
|
||||
python3 mailbox_manager.py sync
|
||||
|
||||
# 列出所有邮件
|
||||
python3 mailbox_manager.py list
|
||||
|
||||
# 按状态筛选
|
||||
python3 mailbox_manager.py list pending
|
||||
python3 mailbox_manager.py list done
|
||||
|
||||
# 显示邮件详情
|
||||
python3 mailbox_manager.py show 42
|
||||
|
||||
# 更新状态
|
||||
python3 mailbox_manager.py read 42 # 标记已读
|
||||
python3 mailbox_manager.py pending 42 # 待处理
|
||||
python3 mailbox_manager.py processing 42 # 处理中
|
||||
python3 mailbox_manager.py done 42 完成任务 # 已完成(可加备注)
|
||||
|
||||
# 归档邮件
|
||||
python3 mailbox_manager.py archive 42
|
||||
```
|
||||
|
||||
## 工作流建议
|
||||
|
||||
1. **同步邮件**: `python3 mailbox_manager.py sync`
|
||||
2. **查看列表**: `python3 mailbox_manager.py list`
|
||||
3. **查看详情**: `python3 mailbox_manager.py show <id>`
|
||||
4. **处理邮件**:
|
||||
- 标记为 `pending` 等待处理
|
||||
- 处理时标记为 `processing`
|
||||
- 完成后标记为 `done`(可加备注)
|
||||
5. **归档**: 定期归档已完成的邮件
|
||||
|
||||
## AI 使用说明
|
||||
|
||||
扣德在处理邮件时应:
|
||||
1. 先同步邮件:`sync`
|
||||
2. 查看未处理邮件:`list pending` 或 `list unread`
|
||||
3. 读取邮件详情:`show <id>`
|
||||
4. 根据邮件内容执行任务
|
||||
5. 完成后更新状态:`done <id> 处理说明`
|
||||
6. 定期归档旧邮件
|
||||
BIN
works/mailbox/__pycache__/mailbox_manager.cpython-310.pyc
Normal file
BIN
works/mailbox/__pycache__/mailbox_manager.cpython-310.pyc
Normal file
Binary file not shown.
27
works/mailbox/emails/1/body.txt
Normal file
27
works/mailbox/emails/1/body.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
你按照下面的方案,开发一下
|
||||
|
||||
A股板块分析方案汇总
|
||||
|
||||
一、方案对比
|
||||
东方财富API ★★★★★ 推荐
|
||||
|
||||
二、推荐方案:东方财富HTTP API
|
||||
- 行业/概念板块涨跌幅排行
|
||||
- 主力资金净流入/流出
|
||||
- 领涨股/领跌股
|
||||
|
||||
三、代码示例(已验证可用)
|
||||
|
||||
四、需要解决的问题
|
||||
1. 代理问题 - 已解决
|
||||
2. 数据更新时机
|
||||
3. API稳定性
|
||||
|
||||
五、后续可扩展功能
|
||||
1. 板块监控脚本
|
||||
2. 个股-板块关联
|
||||
3. 数据存储
|
||||
4. AI增强
|
||||
|
||||
六、实施建议
|
||||
七、今日测试数据示例
|
||||
11
works/mailbox/emails/1/meta.json
Normal file
11
works/mailbox/emails/1/meta.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "1",
|
||||
"subject": "Fw: A股板块分析方案汇总",
|
||||
"sender": "wlq@tphai.com",
|
||||
"date": "Fri, 10 Apr 2026 16:38:39 +0800",
|
||||
"has_attachment": false,
|
||||
"status": "done",
|
||||
"created_at": "2026-04-10T23:41:34.414741",
|
||||
"updated_at": "2026-04-10T23:41:34.415832",
|
||||
"notes": "board_monitor项目已实现全部功能:东方财富API、代理问题已解决、历史数据存储、每日盘后报告"
|
||||
}
|
||||
14
works/mailbox/inbox.json
Normal file
14
works/mailbox/inbox.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"description": "邮件收件箱状态追踪",
|
||||
"last_check": null,
|
||||
"emails": {
|
||||
"1": {
|
||||
"subject": "Fw: A股板块分析方案汇总",
|
||||
"sender": "wlq@tphai.com",
|
||||
"date": "Fri, 10 Apr 2026 16:38:39 +0800",
|
||||
"status": "done",
|
||||
"has_attachment": false,
|
||||
"path": "/home/xian/.openclaw/workspace-coder/works/mailbox/emails/1"
|
||||
}
|
||||
}
|
||||
}
|
||||
362
works/mailbox/mailbox_manager.py
Normal file
362
works/mailbox/mailbox_manager.py
Normal file
@@ -0,0 +1,362 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
邮件收件箱管理工具
|
||||
管理已读邮件内容和处理状态
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
# 路径配置
|
||||
SCRIPT_DIR = Path(__file__).parent
|
||||
MAILBOX_DIR = SCRIPT_DIR
|
||||
INBOX_FILE = MAILBOX_DIR / "inbox.json"
|
||||
EMAILS_DIR = MAILBOX_DIR / "emails"
|
||||
ARCHIVE_DIR = MAILBOX_DIR / "archive"
|
||||
|
||||
# 状态定义
|
||||
STATUS_UNREAD = "unread"
|
||||
STATUS_READ = "read"
|
||||
STATUS_PENDING = "pending" # 待处理
|
||||
STATUS_PROCESSING = "processing" # 处理中
|
||||
STATUS_DONE = "done" # 已完成
|
||||
STATUS_ARCHIVED = "archived" # 已归档
|
||||
|
||||
|
||||
def load_inbox():
|
||||
"""加载收件箱状态"""
|
||||
if not INBOX_FILE.exists():
|
||||
return {"description": "邮件收件箱状态追踪", "last_check": None, "emails": {}}
|
||||
with open(INBOX_FILE, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def save_inbox(data):
|
||||
"""保存收件箱状态"""
|
||||
with open(INBOX_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
|
||||
|
||||
def add_email(email_id, subject, sender, date, has_attachment=False, body="", status=STATUS_UNREAD):
|
||||
"""添加或更新邮件记录"""
|
||||
inbox = load_inbox()
|
||||
|
||||
email_dir = EMAILS_DIR / str(email_id)
|
||||
email_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# 保存邮件内容
|
||||
meta = {
|
||||
"id": email_id,
|
||||
"subject": subject,
|
||||
"sender": sender,
|
||||
"date": date,
|
||||
"has_attachment": has_attachment,
|
||||
"status": status,
|
||||
"created_at": datetime.now().isoformat(),
|
||||
"updated_at": datetime.now().isoformat(),
|
||||
"notes": ""
|
||||
}
|
||||
|
||||
with open(email_dir / "meta.json", "w", encoding="utf-8") as f:
|
||||
json.dump(meta, f, ensure_ascii=False, indent=2)
|
||||
|
||||
if body:
|
||||
with open(email_dir / "body.txt", "w", encoding="utf-8") as f:
|
||||
f.write(body)
|
||||
|
||||
# 更新收件箱索引
|
||||
inbox["emails"][str(email_id)] = {
|
||||
"subject": subject,
|
||||
"sender": sender,
|
||||
"date": date,
|
||||
"status": status,
|
||||
"has_attachment": has_attachment,
|
||||
"path": str(email_dir)
|
||||
}
|
||||
|
||||
save_inbox(inbox)
|
||||
print(f"✅ 邮件 [{email_id}] 已添加到收件箱")
|
||||
|
||||
|
||||
def update_status(email_id, status, notes=None):
|
||||
"""更新邮件状态"""
|
||||
inbox = load_inbox()
|
||||
email_key = str(email_id)
|
||||
|
||||
if email_key not in inbox["emails"]:
|
||||
print(f"❌ 邮件 [{email_id}] 不存在")
|
||||
return False
|
||||
|
||||
# 更新索引
|
||||
inbox["emails"][email_key]["status"] = status
|
||||
|
||||
# 更新邮件详情
|
||||
email_dir = Path(inbox["emails"][email_key]["path"])
|
||||
meta_file = email_dir / "meta.json"
|
||||
|
||||
if meta_file.exists():
|
||||
with open(meta_file, "r", encoding="utf-8") as f:
|
||||
meta = json.load(f)
|
||||
|
||||
meta["status"] = status
|
||||
meta["updated_at"] = datetime.now().isoformat()
|
||||
|
||||
if notes:
|
||||
meta["notes"] = notes
|
||||
|
||||
with open(meta_file, "w", encoding="utf-8") as f:
|
||||
json.dump(meta, f, ensure_ascii=False, indent=2)
|
||||
|
||||
save_inbox(inbox)
|
||||
|
||||
status_emoji = {
|
||||
STATUS_UNREAD: "📬",
|
||||
STATUS_READ: "📖",
|
||||
STATUS_PENDING: "⏳",
|
||||
STATUS_PROCESSING: "🔄",
|
||||
STATUS_DONE: "✅",
|
||||
STATUS_ARCHIVED: "📦"
|
||||
}
|
||||
|
||||
print(f"{status_emoji.get(status, '📧')} 邮件 [{email_id}] 状态更新为: {status}")
|
||||
return True
|
||||
|
||||
|
||||
def list_emails(status_filter=None):
|
||||
"""列出邮件"""
|
||||
inbox = load_inbox()
|
||||
|
||||
if not inbox["emails"]:
|
||||
print("📭 收件箱为空")
|
||||
return
|
||||
|
||||
status_emoji = {
|
||||
STATUS_UNREAD: "📬",
|
||||
STATUS_READ: "📖",
|
||||
STATUS_PENDING: "⏳",
|
||||
STATUS_PROCESSING: "🔄",
|
||||
STATUS_DONE: "✅",
|
||||
STATUS_ARCHIVED: "📦"
|
||||
}
|
||||
|
||||
print("📬 邮件收件箱")
|
||||
print("=" * 60)
|
||||
|
||||
count = 0
|
||||
for email_id, info in sorted(inbox["emails"].items(), key=lambda x: x[0], reverse=True):
|
||||
if status_filter and info["status"] != status_filter:
|
||||
continue
|
||||
|
||||
emoji = status_emoji.get(info["status"], "📧")
|
||||
attach = "📎" if info.get("has_attachment") else ""
|
||||
|
||||
print(f"\n[{email_id}] {emoji} {attach}")
|
||||
print(f" 主题: {info['subject']}")
|
||||
print(f" 发件人: {info['sender']}")
|
||||
print(f" 时间: {info['date']}")
|
||||
print(f" 状态: {info['status']}")
|
||||
count += 1
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print(f"共 {count} 封邮件")
|
||||
|
||||
|
||||
def show_email(email_id):
|
||||
"""显示邮件详情"""
|
||||
inbox = load_inbox()
|
||||
email_key = str(email_id)
|
||||
|
||||
if email_key not in inbox["emails"]:
|
||||
print(f"❌ 邮件 [{email_id}] 不存在")
|
||||
return
|
||||
|
||||
email_dir = Path(inbox["emails"][email_key]["path"])
|
||||
meta_file = email_dir / "meta.json"
|
||||
body_file = email_dir / "body.txt"
|
||||
|
||||
print(f"📧 邮件详情 [{email_id}]")
|
||||
print("=" * 60)
|
||||
|
||||
if meta_file.exists():
|
||||
with open(meta_file, "r", encoding="utf-8") as f:
|
||||
meta = json.load(f)
|
||||
|
||||
print(f"主题: {meta.get('subject', 'N/A')}")
|
||||
print(f"发件人: {meta.get('sender', 'N/A')}")
|
||||
print(f"时间: {meta.get('date', 'N/A')}")
|
||||
print(f"状态: {meta.get('status', 'N/A')}")
|
||||
print(f"更新时间: {meta.get('updated_at', 'N/A')}")
|
||||
|
||||
if meta.get('notes'):
|
||||
print(f"\n备注: {meta['notes']}")
|
||||
|
||||
if body_file.exists():
|
||||
print("\n正文:")
|
||||
print("-" * 40)
|
||||
with open(body_file, "r", encoding="utf-8") as f:
|
||||
print(f.read())
|
||||
|
||||
# 列出附件
|
||||
attach_dir = email_dir / "attachments"
|
||||
if attach_dir.exists() and list(attach_dir.iterdir()):
|
||||
print("\n附件:")
|
||||
print("-" * 40)
|
||||
for f in attach_dir.iterdir():
|
||||
print(f" 📎 {f.name}")
|
||||
|
||||
|
||||
def archive_email(email_id):
|
||||
"""归档邮件"""
|
||||
inbox = load_inbox()
|
||||
email_key = str(email_id)
|
||||
|
||||
if email_key not in inbox["emails"]:
|
||||
print(f"❌ 邮件 [{email_id}] 不存在")
|
||||
return False
|
||||
|
||||
email_dir = Path(inbox["emails"][email_key]["path"])
|
||||
|
||||
# 移动到归档目录
|
||||
archive_path = ARCHIVE_DIR / str(email_id)
|
||||
if email_dir.exists():
|
||||
import shutil
|
||||
shutil.move(str(email_dir), str(archive_path))
|
||||
|
||||
# 更新索引
|
||||
inbox["emails"][email_key]["status"] = STATUS_ARCHIVED
|
||||
inbox["emails"][email_key]["path"] = str(archive_path)
|
||||
save_inbox(inbox)
|
||||
|
||||
print(f"📦 邮件 [{email_id}] 已归档")
|
||||
return True
|
||||
|
||||
|
||||
def sync_from_imap():
|
||||
"""从 IMAP 同步未读邮件"""
|
||||
try:
|
||||
# 导入 receive_email 模块
|
||||
email_scripts_dir = Path(__file__).parent.parent.parent / "skills" / "email" / "scripts"
|
||||
sys.path.insert(0, str(email_scripts_dir))
|
||||
from receive_email import list_unread, read_email
|
||||
|
||||
print("🔄 正在同步邮件...")
|
||||
|
||||
emails = list_unread(limit=20, verbose=False)
|
||||
|
||||
if not emails:
|
||||
print("📭 没有新邮件")
|
||||
return
|
||||
|
||||
inbox = load_inbox()
|
||||
new_count = 0
|
||||
|
||||
for e in emails:
|
||||
email_id = str(e['id'])
|
||||
|
||||
# 跳过已存在的邮件
|
||||
if email_id in inbox["emails"]:
|
||||
continue
|
||||
|
||||
# 读取邮件详情
|
||||
detail = read_email(email_id=email_id, save_attachments=True, verbose=False)
|
||||
|
||||
if detail:
|
||||
add_email(
|
||||
email_id=email_id,
|
||||
subject=detail.get('subject', ''),
|
||||
sender=detail.get('from', ''),
|
||||
date=detail.get('date', ''),
|
||||
has_attachment=len(detail.get('attachments', [])) > 0,
|
||||
body=detail.get('body', ''),
|
||||
status=STATUS_UNREAD
|
||||
)
|
||||
new_count += 1
|
||||
|
||||
# 更新最后检查时间
|
||||
inbox["last_check"] = datetime.now().isoformat()
|
||||
save_inbox(inbox)
|
||||
|
||||
print(f"\n✅ 同步完成,新增 {new_count} 封邮件")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 同步失败: {e}")
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("邮件收件箱管理工具")
|
||||
print()
|
||||
print("用法:")
|
||||
print(" python3 mailbox_manager.py sync # 从IMAP同步未读邮件")
|
||||
print(" python3 mailbox_manager.py list [status] # 列出邮件(可按状态筛选)")
|
||||
print(" python3 mailbox_manager.py show <id> # 显示邮件详情")
|
||||
print(" python3 mailbox_manager.py read <id> # 标记为已读")
|
||||
print(" python3 mailbox_manager.py pending <id> # 标记为待处理")
|
||||
print(" python3 mailbox_manager.py processing <id> # 标记为处理中")
|
||||
print(" python3 mailbox_manager.py done <id> [notes] # 标记为已完成")
|
||||
print(" python3 mailbox_manager.py archive <id> # 归档邮件")
|
||||
print()
|
||||
print("状态说明:")
|
||||
print(" unread - 未读")
|
||||
print(" read - 已读")
|
||||
print(" pending - 待处理")
|
||||
print(" processing - 处理中")
|
||||
print(" done - 已完成")
|
||||
print(" archived - 已归档")
|
||||
return
|
||||
|
||||
command = sys.argv[1]
|
||||
|
||||
if command == "sync":
|
||||
sync_from_imap()
|
||||
|
||||
elif command == "list":
|
||||
status = sys.argv[2] if len(sys.argv) > 2 else None
|
||||
list_emails(status)
|
||||
|
||||
elif command == "show":
|
||||
if len(sys.argv) < 3:
|
||||
print("❌ 请指定邮件ID")
|
||||
return
|
||||
show_email(sys.argv[2])
|
||||
|
||||
elif command == "read":
|
||||
if len(sys.argv) < 3:
|
||||
print("❌ 请指定邮件ID")
|
||||
return
|
||||
update_status(sys.argv[2], STATUS_READ)
|
||||
|
||||
elif command == "pending":
|
||||
if len(sys.argv) < 3:
|
||||
print("❌ 请指定邮件ID")
|
||||
return
|
||||
update_status(sys.argv[2], STATUS_PENDING)
|
||||
|
||||
elif command == "processing":
|
||||
if len(sys.argv) < 3:
|
||||
print("❌ 请指定邮件ID")
|
||||
return
|
||||
update_status(sys.argv[2], STATUS_PROCESSING)
|
||||
|
||||
elif command == "done":
|
||||
if len(sys.argv) < 3:
|
||||
print("❌ 请指定邮件ID")
|
||||
return
|
||||
notes = " ".join(sys.argv[3:]) if len(sys.argv) > 3 else None
|
||||
update_status(sys.argv[2], STATUS_DONE, notes)
|
||||
|
||||
elif command == "archive":
|
||||
if len(sys.argv) < 3:
|
||||
print("❌ 请指定邮件ID")
|
||||
return
|
||||
archive_email(sys.argv[2])
|
||||
|
||||
else:
|
||||
print(f"❌ 未知命令: {command}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
1
works/multi-agent-bidding
Submodule
1
works/multi-agent-bidding
Submodule
Submodule works/multi-agent-bidding added at 43f758807e
Submodule works/param-hub updated: 0561c6da6f...f249f28eb7
1
works/param-hub-python
Submodule
1
works/param-hub-python
Submodule
Submodule works/param-hub-python added at 627148a87f
Submodule works/pdf-translate-web-v2 updated: 2ef5e6da87...d338522692
1
works/project-panel
Submodule
1
works/project-panel
Submodule
Submodule works/project-panel added at c73196dad3
1
works/service-monitor
Submodule
1
works/service-monitor
Submodule
Submodule works/service-monitor added at a7cc60596e
1
works/snippet-notes
Submodule
1
works/snippet-notes
Submodule
Submodule works/snippet-notes added at 8c4c0af053
1
works/xian-favor
Submodule
1
works/xian-favor
Submodule
Submodule works/xian-favor added at 184cc5b56b
Reference in New Issue
Block a user