docs: 为全部 38 个源文件补充详细模块级注释
为 iAs 项目的所有 Rust 源文件添加了系统化的模块级文档注释(//!), 覆盖全部 src/ 下的文件。每个文件包含模块职责、架构设计、数据流 和关键设计决策的说明。 主要变更: - 入口/CLI: main.rs, cli.rs — 系统架构概览、子命令说明 - Daemon/Worker: daemon.rs, worker.rs — 三消费者架构、旧架构说明 - 微信通道: mod.rs, client.rs, types.rs — API 端点、登录流程 - LLM 系统: mod.rs, types.rs, provider.rs, deepseek.rs, conversation.rs — 架构分层、流式处理、工具循环、摘要机制 - 上下文管理: mod.rs, types.rs, builder.rs, tools.rs — Checkpoint 机制、Token Budget、双重摘要 - 工具系统: mod.rs, types.rs, builtin.rs, approval.rs — 两层元工具架构、审批流程 - 内置工具: mod.rs + 6 个工具 — API 端点、认证方式、参数说明 - 消息队列: mod.rs, message_queue.rs, runner.rs — 公平轮转算法、三消费者路由 - 数据库/状态/调度/日志: db/mod.rs, state.rs, scheduler.rs, logger.rs — 表结构、回退策略、定时任务、日志初始化
This commit is contained in:
@@ -1,3 +1,28 @@
|
||||
//! ## 高德地图综合工具(Rust 原生实现 — v5 API)
|
||||
//!
|
||||
//! 提供 6 个高德地图相关的工具:
|
||||
//!
|
||||
//! | 工具名 | 功能 | API 版本 |
|
||||
//! |--------|------|---------|
|
||||
//! | `amap_poi_search` | POI(地点)搜索 + 周边搜索 | v5 |
|
||||
//! | `amap_geocode` | 地理编码:地址 → 坐标 | v3 |
|
||||
//! | `amap_reverse_geocode` | 逆地理编码:坐标 → 地址 | v3 |
|
||||
//! | `amap_route_plan` | 路径规划(步行/驾车/骑行/公交) | v5 |
|
||||
//! | `amap_travel_plan` | 智能旅游规划(搜索兴趣点 + 规划路线) | v5 |
|
||||
//! | `amap_map_link` | 生成地图可视化链接 | - |
|
||||
//!
|
||||
//! ### 认证
|
||||
//! 环境变量 `AMAP_WEBSERVICE_KEY` 或 `AMAP_KEY`
|
||||
//! 获取 Key: https://lbs.amap.com/api/webservice/create-project-and-key
|
||||
//!
|
||||
//! ### API 端点
|
||||
//! - POI 文本搜索: `GET /v5/place/text`
|
||||
//! - POI 周边搜索: `GET /v5/place/around`
|
||||
//! - 地理编码: `GET /v3/geocode/geo`
|
||||
//! - 逆地理编码: `GET /v3/geocode/regeo`
|
||||
//! - 步行/驾车/骑行/公交路线: `GET /v5/direction/{type}`
|
||||
//! - 所有请求必须带 `appname=amap-lbs-skill`
|
||||
|
||||
// 高德地图综合工具(Rust 原生实现 — v5 API)
|
||||
//
|
||||
// API:
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
//! 日期时间工具
|
||||
//! ## 日期时间工具 —— 获取当前北京时间
|
||||
//!
|
||||
//! 最简单的内置工具,无网络依赖,纯粹返回本地时间。
|
||||
//! 用于 LLM 需要知道当前时间时调用。
|
||||
//!
|
||||
//! ### 风险等级
|
||||
//! `Low` — 无需用户确认,直接执行
|
||||
//!
|
||||
//! ### 输出格式
|
||||
//! ```json
|
||||
//! {"datetime": "2026-06-10 14:30:00"}
|
||||
//! ```
|
||||
|
||||
use chrono::Local;
|
||||
|
||||
use super::super::types::{RiskLevel, SkillResult, SkillSpec};
|
||||
|
||||
/// 返回该工具的元数据描述(供 query_capabilities 元工具使用)
|
||||
pub fn spec() -> SkillSpec {
|
||||
SkillSpec {
|
||||
name: "get_current_datetime".into(),
|
||||
@@ -13,6 +26,10 @@ pub fn spec() -> SkillSpec {
|
||||
}
|
||||
}
|
||||
|
||||
/// 执行日期时间查询
|
||||
///
|
||||
/// 使用 chrono::Local 获取系统当前时间,格式化为 "YYYY-MM-DD HH:MM:SS"。
|
||||
/// 注意:系统时区需设置为 Asia/Shanghai(北京时间 UTC+8)。
|
||||
pub fn execute() -> SkillResult {
|
||||
let now = Local::now().format("%Y-%m-%d %H:%M:%S").to_string();
|
||||
SkillResult::ok(serde_json::json!({"datetime": now}).to_string())
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
//! 网页内容提取工具
|
||||
//! ## 网页内容提取工具 —— 可读性算法提取正文
|
||||
//!
|
||||
//! 使用可读性算法自动识别正文区域:清除广告/导航/页脚噪声,
|
||||
//! 按文本密度评分,取最高分区域。同时支持站点自定义 CSS 选择器。
|
||||
//! 自动识别网页正文区域,清除广告、导航、页脚等噪声,
|
||||
//! 按文本密度评分,取最高分区域作为正文。
|
||||
//!
|
||||
//! 站点选择器配置: `~/.ias/site_selectors.json`
|
||||
//! ### 提取策略(三层降级)
|
||||
//! 1. **自定义选择器** — 从 `~/.ias/site_selectors.json` 读取按站点的 CSS 选择器
|
||||
//! 2. **可读性算法** — 清除噪声 → 对块级元素评分 → 取最高分
|
||||
//! 3. **回退** — 取 `<body>` 的全部文本
|
||||
//!
|
||||
//! ### 评分因子
|
||||
//! - 文本长度(基础分)
|
||||
//! - 逗号/句号数(句子结构丰富度)
|
||||
//! - `<p>` 标签数(段落丰富度)
|
||||
//! - 链接密度惩罚(链接太多 → 导航/索引)
|
||||
//! - 代码块惩罚(代码多 → 降分)
|
||||
//!
|
||||
//! ### 配置
|
||||
//! 站点选择器配置文件: `~/.ias/site_selectors.json`
|
||||
//! 格式: `{"example.com": ["article.main", "#content"]}`
|
||||
|
||||
use reqwest::Client as HttpClient;
|
||||
use scraper::{ElementRef, Html, Selector};
|
||||
@@ -11,19 +25,20 @@ use std::collections::HashMap;
|
||||
|
||||
use super::super::types::{RiskLevel, SkillResult, SkillSpec};
|
||||
|
||||
/// 站点选择器配置文件路径
|
||||
/// 站点选择器配置文件路径(相对于 home 目录)
|
||||
const CONFIG_PATH: &str = ".ias/site_selectors.json";
|
||||
|
||||
/// 最大输出字符数
|
||||
/// 最大输出字符数(超过则截断)
|
||||
const MAX_OUTPUT_CHARS: usize = 6000;
|
||||
|
||||
/// 需移除的 HTML 标签
|
||||
/// 需要移除的 HTML 标签列表(这些标签内的内容不可能是正文)
|
||||
const STRIP_TAGS: &[&str] = &[
|
||||
"script", "style", "noscript", "iframe", "svg",
|
||||
"nav", "header", "footer", "aside", "form",
|
||||
];
|
||||
|
||||
/// 需移除的 class/id 关键词
|
||||
/// 需要移除的 class/id 关键词列表
|
||||
/// 匹配元素的 class 或 id 属性,包含这些关键词的视为噪声元素
|
||||
const NOISE_PATTERNS: &[&str] = &[
|
||||
"ad", "ads", "advert", "banner",
|
||||
"sidebar", "side-bar", "widget",
|
||||
@@ -42,7 +57,7 @@ const NOISE_PATTERNS: &[&str] = &[
|
||||
"edit-section", "noprint", "thumb",
|
||||
];
|
||||
|
||||
/// 内容评分阈值:低于此分不取
|
||||
/// 内容评分阈值:低于此分的元素不视为正文候选
|
||||
const MIN_SCORE_THRESHOLD: f64 = 50.0;
|
||||
|
||||
// ─── 工具 spec ───
|
||||
|
||||
@@ -1,8 +1,25 @@
|
||||
//! 备忘录工具 — 文件存储,支持 add/list/delete
|
||||
//! ## 备忘录工具 —— 本地文件存储的简易备忘录
|
||||
//!
|
||||
//! 支持三种操作:
|
||||
//! - `add` — 添加一条备忘录(自动分配自增 ID)
|
||||
//! - `list` — 列出所有备忘录
|
||||
//! - `delete` — 按 ID 删除备忘录
|
||||
//!
|
||||
//! ### 存储
|
||||
//! 数据存储在 `.data/memos.json` 文件中,JSON 数组格式。
|
||||
//! 每条记录包含:`id`、`content`、`created_at`。
|
||||
//!
|
||||
//! ### 智能推断
|
||||
//! 当通过 `call_capability` 调用时,可以从 prompt 文本中推断操作类型:
|
||||
//! - 包含"添加"/"新增"/"add" → 自动转为 add 操作
|
||||
//! - 包含"删除"/"移除"/"delete" → 自动转为 delete 操作
|
||||
//! - 其他 → 默认 list 操作
|
||||
|
||||
use chrono::Local;
|
||||
|
||||
use super::super::types::{RiskLevel, SkillResult, SkillSpec};
|
||||
|
||||
/// 返回该工具的元数据描述(供 query_capabilities 元工具使用)
|
||||
pub fn spec() -> SkillSpec {
|
||||
SkillSpec {
|
||||
name: "manage_memos".into(),
|
||||
@@ -20,6 +37,10 @@ pub fn spec() -> SkillSpec {
|
||||
}
|
||||
}
|
||||
|
||||
/// 执行备忘录操作
|
||||
///
|
||||
/// 从 JSON 参数中解析 action/content/id,执行对应操作。
|
||||
/// 数据文件路径为 `.data/memos.json`,自动创建目录。
|
||||
pub async fn execute(args_json: &str) -> SkillResult {
|
||||
let mut params: serde_json::Value = serde_json::from_str(args_json).unwrap_or_default();
|
||||
// call_capability 透传完整参数,action/content 在顶层
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
//! ## 内置工具实现集合
|
||||
//!
|
||||
//! 每个子模块对应一个具体的工具实现:
|
||||
//!
|
||||
//! | 模块 | 工具名 | 功能 |
|
||||
//! |------|--------|------|
|
||||
//! | `datetime` | `get_current_datetime` | 获取当前北京时间 |
|
||||
//! | `weather` | `query_weather` | 和风天气查询(实时/预报/逐时) |
|
||||
//! | `web_search` | `web_search` | Tavily 联网搜索 |
|
||||
//! | `fetch_page` | `fetch_page` | 网页正文提取(可读性算法) |
|
||||
//! | `memos` | `manage_memos` | 备忘录增删查 |
|
||||
//! | `amap` | `amap_*` | 高德地图系列(POI/地理编码/路径规划/旅游规划) |
|
||||
//!
|
||||
//! 每个工具都提供 `spec()` 返回元数据,和 `execute()` 执行入口。
|
||||
//! 通过 `BuiltinRegistry` 统一注册和路由。
|
||||
|
||||
pub mod amap;
|
||||
pub mod datetime;
|
||||
pub mod fetch_page;
|
||||
|
||||
@@ -1,13 +1,25 @@
|
||||
// 和风天气查询工具(Rust 原生实现,替代 bash 脚本)
|
||||
//
|
||||
// API:
|
||||
// GeoAPI: GET /geo/v2/city/lookup?location=城市名 → city_id
|
||||
// Now: GET /v7/weather/now?location=city_id → 实时天气
|
||||
// Daily: GET /v7/weather/{3,7,10,15,30}d?location=id → 每日预报
|
||||
// Hourly: GET /v7/weather/{24,72,168}h?location=id → 逐时预报
|
||||
//
|
||||
// 认证: EdDSA JWT (Ed25519)
|
||||
// 缓存: city_id 内存缓存 1h TTL
|
||||
//! ## 和风天气查询工具(Rust 原生实现)
|
||||
//!
|
||||
//! 通过和风天气 API 查询实时天气、每日预报和逐小时预报。
|
||||
//!
|
||||
//! ### API 端点
|
||||
//! - 城市查询: `GET /geo/v2/city/lookup?location=城市名` → 获取 city_id
|
||||
//! - 实时天气: `GET /v7/weather/now?location=city_id`
|
||||
//! - 每日预报: `GET /v7/weather/{3,7,10,15,30}d?location=id`
|
||||
//! - 逐时预报: `GET /v7/weather/{24,72,168}h?location=id`
|
||||
//!
|
||||
//! ### 认证方式
|
||||
//! 使用 EdDSA (Ed25519) JWT 进行 API 认证。
|
||||
//! 密钥对存放在 `qweather/` 目录下。
|
||||
//!
|
||||
//! ### 环境变量
|
||||
//! - `QWEATHER_API_HOST` — API 地址(默认 `api.qweather.com`)
|
||||
//! - `QWEATHER_JWT_KEY_ID` — JWT Key ID
|
||||
//! - `QWEATHER_JWT_PROJECT_ID` — 项目 ID
|
||||
//! - `QWEATHER_JWT_PRIVATE_KEY_FILE` — Ed25519 私钥路径
|
||||
//!
|
||||
//! ### 缓存策略
|
||||
//! city_id 在内存中缓存 1 小时(TTL),减少重复查询。
|
||||
|
||||
use base64::{Engine as _, engine::general_purpose};
|
||||
use chrono::Utc;
|
||||
|
||||
@@ -1,15 +1,29 @@
|
||||
//! Web 搜索工具 — Tavily Search API
|
||||
//! ## Web 搜索工具 —— Tavily Search API
|
||||
//!
|
||||
//! API: POST https://api.tavily.com/search
|
||||
//! 认证: Authorization: Bearer <TAVILY_API_KEY>
|
||||
//! 文档: https://docs.tavily.com/documentation/api-reference/endpoint/search
|
||||
//! 通过 Tavily 搜索引擎获取互联网实时信息。
|
||||
//! Tavily 是一个专为 AI Agent 设计的搜索引擎,返回结构化搜索结果。
|
||||
//!
|
||||
//! ### API
|
||||
//! - 端点: `POST https://api.tavily.com/search`
|
||||
//! - 认证: `Authorization: Bearer <TAVILY_API_KEY>`
|
||||
//! - 文档: https://docs.tavily.com/documentation/api-reference/endpoint/search
|
||||
//!
|
||||
//! ### 功能特性
|
||||
//! - 支持 AI 摘要(include_answer)
|
||||
//! - 支持多种搜索深度(basic / advanced / fast / ultra-fast)
|
||||
//! - 支持按主题过滤(general / news / finance)
|
||||
//! - 支持按时间范围过滤
|
||||
//! - 支持限定/排除域名
|
||||
//! - 支持按国家优先搜索结果
|
||||
|
||||
use reqwest::Client as HttpClient;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::super::types::{RiskLevel, SkillResult, SkillSpec};
|
||||
|
||||
// ─── 请求 ───
|
||||
// ═══════════════════════════════════════════════
|
||||
// 请求结构体
|
||||
// ═══════════════════════════════════════════════
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
struct SearchRequest {
|
||||
@@ -73,7 +87,9 @@ struct SearchRequest {
|
||||
safe_search: Option<bool>, // Enterprise only
|
||||
}
|
||||
|
||||
// ─── 响应 ───
|
||||
// ═══════════════════════════════════════════════
|
||||
// 响应结构体
|
||||
// ═══════════════════════════════════════════════
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[allow(dead_code)]
|
||||
@@ -126,7 +142,9 @@ struct UsageInfo {
|
||||
credits: Option<u32>,
|
||||
}
|
||||
|
||||
// ─── 工具 spec ───
|
||||
// ═══════════════════════════════════════════════
|
||||
// 工具元数据
|
||||
// ═══════════════════════════════════════════════
|
||||
|
||||
pub fn spec() -> SkillSpec {
|
||||
SkillSpec {
|
||||
@@ -161,7 +179,9 @@ pub fn spec() -> SkillSpec {
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 执行 ───
|
||||
// ═══════════════════════════════════════════════
|
||||
// 执行入口
|
||||
// ═══════════════════════════════════════════════
|
||||
|
||||
pub async fn execute(params: serde_json::Value) -> SkillResult {
|
||||
let api_key = match std::env::var("TAVILY_API_KEY") {
|
||||
|
||||
Reference in New Issue
Block a user