@someok/pi-deepseek-web-tools0.3.0
pi 扩展:DeepSeek 网页搜索(ds_search)与网页抓取(ds_fetch),GitHub 链接自动 clone 仓库并渲染 PR/Issue
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-deepseek-web-tools
简体中文 | English
给 pi 加两个工具:ds_search(DeepSeek 网页搜索)和 ds_fetch(网页抓取)。普通网页走 DeepSeek 官方 Search / Fetch API;GitHub 链接自动改走本地 git / gh,仓库直接克隆到本地让模型翻源码,PR/Issue 渲染成结构化文档。
配置齐全时两个工具都可用;没配 DeepSeek key 时 ds_search 和普通网页抓取不可用,但 ds_fetch 的 GitHub 部分照常工作。
安装
# 从 npm 安装(推荐),之后每次启动都加载
pi install npm:@someok/pi-deepseek-web-tools
# 只试一次,不写设置
pi -e npm:@someok/pi-deepseek-web-tools
# 开发时从本地目录加载
pi -e ./
之前用 pi install ./ 装过本地路径的,先用 pi list 找到那一条并 pi remove <本地路径>,再装 npm 包。两个入口同时存在会重复加载同一个扩展,工具名冲突会直接报错。
配置
两个配置文件结构相同,项目级优先:
| 层级 | 路径 |
|---|---|
| 项目级 | <项目>/.pi/deepseek-web-tools.json |
| 用户级 | ~/.pi/agent/deepseek-web-tools.json($PI_CODING_AGENT_DIR 覆盖时按该目录) |
| 环境变量 | DEEPSEEK_API_KEY |
项目级配置只在项目已受信任时读取,和 pi 处理 .pi/ 的规则一致。
完整示例(也见仓库里的 deepseek-web-tools.example.json):
{
"enabled": true,
"apiKey": "sk-...",
"baseUrl": "https://api.deepseek.com",
"exposure": {
"search": "codemode",
"fetch": "direct"
},
"search": {
"timeoutMs": 30000,
"count": 10,
"needContent": false
},
"fetch": {
"timeoutMs": 90000
},
"github": {
"enabled": true,
"prIssue": true,
"maxRepoSizeMB": 350,
"cloneTimeoutSeconds": 30,
"clonePath": "~/pi-github-repos"
}
}
合并规则:逐字段取「项目级 → 用户级 → 默认值」;apiKey 再回退到 DEEPSEEK_API_KEY。
| 字段 | 默认 | 说明 |
|---|---|---|
enabled |
有 apiKey 即启用 | false 强制关闭,即使环境变量有 key |
apiKey |
无 | 空白字符串视为没写 |
baseUrl |
https://api.deepseek.com |
尾部斜杠会被去掉 |
exposure |
{ "search": "codemode", "fetch": "direct" } |
按工具分别配:codemode 隐藏声明、只能从脚本调用,direct 直接声明给模型。写字符串("direct" / "codemode")表示两个工具都用这个值 |
search.timeoutMs |
30000 |
1000~300000 |
search.count |
不发送(API 默认 10) | 1~50 |
search.needContent |
false |
是否在搜索结果里带网页正文 |
fetch.timeoutMs |
90000 |
1000~300000 |
github.enabled |
true |
关掉后 ds_fetch 不再走 GitHub 专用路径 |
github.prIssue |
true |
是否用 gh 把 PR/Issue 渲染成结构化文档 |
github.maxRepoSizeMB |
350 |
超过这个体积改用 GitHub API 轻量视图,不克隆 |
github.cloneTimeoutSeconds |
30 |
1~600,超时后连 git 子进程一起杀掉 |
github.clonePath |
系统临时目录下 pi-github-repos |
支持 ~ 和 $HOME 这类写法 |
配置写错(坏 JSON、字段类型不对、拼错键名)不会让扩展崩掉:出问题的字段被忽略并记一条告警,启动时和 /ds-tool-config 里能看到。改完配置执行 /reload 生效。
工具
ds_search
| 参数 | 必填 | 说明 |
|---|---|---|
query |
是 | 1~128 字符,支持 site:、-site:、"短语"、lang:、after:、before: |
count |
否 | 1~50,不传时用 search.count |
needContent |
否 | 是否返回正文,默认用 search.needContent |
返回带编号的结果列表(标题 / URL / 站点与发布时间 / 摘要)。结果超过 2000 行或 50KB 时会截断,完整 JSON 落到临时文件,路径写在结尾。
ds_fetch
| 参数 | 必填 | 说明 |
|---|---|---|
url |
是 | 必须是带 host 的 HTTP/HTTPS 地址,不带用户名密码,长度 ≤8192 |
返回页面标题加 Markdown 正文。正文同样按 2000 行 / 50KB 截断,完整内容落临时文件。
遇到 github.com 链接会自动改走专用路径,详见下一节。
GitHub 链接
ds_fetch 拿到 github.com 的 URL 时不再走 DeepSeek,而是按 URL 类型分派:
| URL | 处理方式 |
|---|---|
github.com/owner/repo |
克隆到本地,返回目录树 + README + 本地路径 |
.../tree/main/src |
返回该目录的文件列表(带大小) |
.../blob/main/src/index.ts |
返回文件内容;二进制文件只说明类型和大小 |
.../pull/123、.../issues/7 |
用 gh 取数,渲染成一份带状态、分支、CI、review、文件、commits、评论的文档 |
超过 maxRepoSizeMB 的仓库 |
自动改用 GitHub API 的轻量视图(tree + README) |
.../commit/<sha> |
直接走 API,不为看一个提交克隆整个仓库 |
克隆只拉一个分支的一层历史(--depth 1 --single-branch),同一个仓库重复抓取会复用本地目录。
依赖:git 必需;gh 可选,但装了才有完整的 PR/Issue 视图和私有仓库访问,没有 gh 时 PR/Issue 会回落到普通网页抓取。GitHub 这条路不消耗 DeepSeek 额度。
界面上的显示
- 工具行默认折叠,只显示结果条数或字符数;展开后显示工具返回的全部文本,不再按行数二次截断。
/ds-search、/ds-fetch的结果同样默认折叠,展开方式:Ctrl+O或鼠标点击;抓取结果按 Markdown 渲染(标题、列表、代码块、链接)。- DeepSeek 的 Fetch 接口会把正文里的标点全转义(
\#、\-、\,、\/),插件进来时先统一去转义,再渲染和给模型,所以界面上看不到反斜杠。Markdown 渲染关掉了 LaTeX 解析,(a 100K context is enough)这类括号不会当成公式。 - 唯一的上限是 2000 行 / 50KB(pi 对模型可见内容的约定):超过时正文末尾会写一行
[输出已截断:… 完整内容:/tmp/…],需要全文时让模型read那个临时文件。
命令
| 命令 | 作用 |
|---|---|
/ds-search <搜索词> |
手动跑一次搜索 |
/ds-fetch <网址> |
手动抓一个网页,支持 /ds-fetch <https://...> 这种粘贴形式 |
/ds-tool-config |
查看当前生效的配置:启用状态、key 来源(脱敏)、超时、两个配置文件是否读到 |
只注册 ds- 前缀的命令,不用 /search、/fetch 这种裸名:/search 已被别的扩展(如 pi-web-access)占用,pi 会给重名命令加 :1、:2 后缀,自己都不知道会拿到哪个。
命令结果写成 custom entry:只在界面上展示,不进模型上下文,模型看不到你手动抓的内容。它们会存进当前会话,恢复会话后仍能翻看。
错误提示
| 状态码 | 含义 | 提示 |
|---|---|---|
| 400 | 参数不合法 | 检查 query 长度、count 范围、URL 格式 |
| 401 | key 缺失或无效 | 检查配置文件或 DEEPSEEK_API_KEY |
| 402 | 余额不足 | 先充值 |
| 403 | Fetch 被安全策略拒绝 | 换站点或跳过 |
| 404 | Search 路径不存在 / Fetch 拿不到正文 | 检查 baseUrl;或目标页不可抓 |
| 408 / 504 | 超时 | 稍后重试 |
| 413 | 请求体过大 | URL 过长 |
| 429 | 触发 QPS 限制 | 稍后重试 |
| 5xx | 服务端错误 | 稍后重试 |
超时由 search.timeoutMs / fetch.timeoutMs 控制,按本地计时中断请求。命令失败会弹 error 提示;工具调用失败表现为失败的工具结果。
限额与计费
- Search 与 Fetch 各自限速 5 QPS(账号级),Fetch 另有目标域名级限制。
- 按成功请求计费:每 1000 次 5 元;Search 无结果、Fetch 没拿到正文、请求失败都不计费。
- DeepSeek 说明:第三方工具直接调用 Search / Fetch 会从 2026-11-01 起按次计费。
开发
npm install
npm run check # tsc --noEmit + vitest
- 运行时不依赖任何 npm 包:普通网页用 Node 内置
fetch,GitHub 用内置child_process调git/gh。 - 测试全部走注入的
fetchImpl或纯函数,不联网。 src/config.ts是纯函数,方便单独测配置合并。
发布到 npm
npm login
npm version patch # 可选:打版本、提交、打 tag
npm publish # 或在 VS Code 的 NPM Scripts 面板里点 release(就是这条)
- 脚本名用
release而不是publish:npm 把publish当成发布后的生命周期钩子,"publish": "npm publish"会发一次再被钩子发一次,第二次因版本已存在而报错。 prepublishOnly会先跑npm run check,typecheck 或测试挂了就不发。- 演练用
npm run release -- --dry-run,不会真的上传。 publishConfig.access已是public(scoped 包不显式声明会默认私有,发布失败)。- 先
npm pack --dry-run看打包内容:当前 14 个文件,只含src/、中英文 README、LICENSE、示例配置,不含测试和计划文档。
安全
apiKey 只出现在发给 DeepSeek 的请求头里,不会写进工具输出、details、structuredContent 或日志。/ds-tool-config 只显示掩码(如 sk-****abcd)。项目级配置含 key 时建议加入 .gitignore(本仓库已忽略 .pi/deepseek-web-tools.json)。