Skip to content

Releases: chenbhao/codev

v2.1.0

Choose a tag to compare

@chenbhao chenbhao released this 24 May 19:17

Desktop app + AI Friend companion

auto create subagent & autodream and auto-compact

Choose a tag to compare

@chenbhao chenbhao released this 18 Apr 16:58

Full Changelog: v2.0.0...v2.0.1

auto create subagent & autodream and auto-compact

WebSearchTool via SearXNG

Choose a tag to compare

@chenbhao chenbhao released this 09 Apr 16:13

🚀 WebSearchTool v2.0.0
✨ Highlights

WebSearchTool v2.0.0 is officially released — now powered by SearXNG.

🔍 Local-first web search
🛡️ Privacy-friendly (no tracking)
🌐 Multi-engine aggregation (Google / Bing / DuckDuckGo...)
🧹 Cleaned & normalized outputs
🧠 Structured for LLM tool-calling

Turn your LLM into a real web agent.

📊 WebSearchTool 执行流程图

执行步骤:

1. 开始性能计时
2. 验证查询参数
3. 发送进度更新(如果有)
4. 调用 searchSearXNG()
5. 清洗搜索结果
6. 格式化输出
7. 返回结果

🔍 searchSearXNG(query)

文件位置: src/tools/WebSearchTool/WebSearchTool.ts:51-92

步骤:

1. 构建请求 URL
   http://localhost:8080/search?q={query}&format=json

2. 设置超时控制 (10 秒)
   const controller = new AbortController()
   const timeout = setTimeout(() => controller.abort(), 10000)

3. 发送 HTTP 请求
   const res = await fetch(url, {
     signal: controller.signal,
     headers: {
       'User-Agent': 'Mozilla/5.0 (compatible; WebSearchTool/1.0)',
       'Accept': 'application/json'
     }
   })

4. 清除超时
   clearTimeout(timeout)

5. 检查 HTTP 状态码
   if (!res.ok) { throw Error(`HTTP ${res.status}`) }

6. 解析 JSON 响应
   const data = await res.json()

7. 提取前 10 个结果
   return (data.results || []).slice(0, 10).map(r => ({
     title: r.title,
     url: r.url,
     snippet: r.content
   }))

🌐 SearXNG 服务

地址: localhost:8080

返回结构:
{
  query: "search term",
  number_of_results: 0,
  results: [
    { title: "...", url: "...", content: "..." },
    ...
  ]
}

🧹 数据清洗 Pipeline

文件位置: src/tools/WebSearchTool/WebSearchTool.ts:95-117

1. stripTags(text)

  • 移除 <script> / <style>

  • 移除所有 HTML 标签

  • 转换 HTML 实体:

    • &amp;&
    • &lt;<
    • &gt;>
    • &quot;"
    • &#39;'
    • &nbsp; → 空格

2. normalizeText(text)

  • 压缩多个空格 → 单个空格
  • 压缩换行 → 最多两个换行
  • 去除首尾空白

3. cleanSearchResult(result)

title   -> stripTags + normalizeText
snippet -> stripTags + normalizeText

✅ 清洗结果示例

{
  "title": "Clean Title",
  "url": "https://example.com",
  "snippet": "Clean snippet without HTML tags"
}

📦 格式化输出

文件位置: src/tools/WebSearchTool/WebSearchTool.ts:219-242

{
  "query": "search term",
  "results": [
    {
      "tool_use_id": "search-1",
      "content": [
        { "title": "...", "url": "...", "snippet": "..." }
      ]
    }
  ],
  "durationSeconds": 0.5
}

🔄 结果映射 (Tool → Claude)

文件位置: src/tools/WebSearchTool/WebSearchTool.ts:244-266

Results for "search term"

1. Title 1
https://url1.com
Snippet 1

2. Title 2
https://url2.com
Snippet 2

返回格式:

{
  "tool_use_id": "toolu_xxx",
  "type": "tool_result",
  "content": "Results for \"search term\"..."
}

🤖 返回给 Claude API

{
  "type": "content",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_xxx",
      "content": "Results..."
    }
  ]
}

🏗️ WebSearchTool 架构图

分层结构

用户层
├── CLI (Ink.js)
├── IDE 插件 (VS Code)
└── Web UI (React)

↓
Claude API 层
├── @anthropic-ai/sdk
│   ├── 消息处理
│   ├── 工具调用
│   └── 流式响应

↓
Query Engine
├── 查询解析
├── 工具调度
└── 响应格式化

↓
Tool Execution Pipeline
├── 工具查找
├── 输入验证 (Zod)
├── 权限检查
├── Hooks
├── tool.call()
└── 结果映射

↓
WebSearchTool 核心
├── 工具定义
├── Schema
├── 核心方法
└── 辅助函数

↓
外部服务
├── SearXNG (localhost:8080)
└── HTTP Fetch

🔄 数据流转换图

阶段 7: stripTags()

输入

{
  "title": "<b>TypeScript</b> Tutorial",
  "snippet": "Learn <a href='#'>TypeScript</a>..."
}

输出

{
  "title": "TypeScript Tutorial",
  "snippet": "Learn TypeScript..."
}

阶段 8: normalizeText()

"with   examples" → "with examples"
"\n\n\n" → "\n\n"

阶段 9: 结果格式化

{
  "query": "typescript tutorial",
  "results": [...],
  "durationSeconds": 0.5
}

阶段 10: 文本转换

Results for "typescript tutorial"

1. Title
URL
Snippet

⚠️ 错误处理流程

❌ HTTP 错误

if (!res.ok) {
  throw new Error(`HTTP ${res.status}`)
}

示例:

  • HTTP 403: Forbidden
  • HTTP 500: Internal Server Error

⏱️ 请求超时

setTimeout(() => controller.abort(), 10000)

错误:

AbortError: The operation was aborted

🧩 JSON 解析失败

SyntaxError: Unexpected token < in JSON

🔍 无搜索结果

if (cleaned.length === 0) {
  output = [`No results for: ${input.query}`]
}

✅ 总结

WebSearchTool 核心流程:

Query
 → SearXNG 请求
 → 数据清洗
 → 结构化输出
 → 文本映射
 → 返回 Claude

Research and Auto Evolve

Choose a tag to compare

@chenbhao chenbhao released this 01 Apr 09:34
v1.0.0

auto research and evolve