Bundle
@deepseek-ai/dsh-tool-pcb-parts-search
DSH PCB parts search tool — search IC/electronic components from eda.cn by keyword for EDA/PCB design
- Source
- Huaqiu-Electronics
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 5 days ago
Readme
# dsh-tool-pcb-parts-search
[English](README.en.md)
DSH PCB 元器件搜索工具插件 —— 按关键词搜索 IC / 有源 / 无源电子元器件,用于 PCB 设计与 EDA 选型。通过芯灵(eda.cn)queryPage 接口查询,默认只返回带 EDA 模型(原理图符号 / PCB 封装)的器件。
[](LICENSE)
## 动机
Agent 做 PCB 设计、原理图绘制、BOM 选型时,需要按型号或描述查找电子元器件。现有路径是起 `bash` 进程让模型现写 `curl` 脚本调搜索引擎:
1. **每次调用都起进程**——Windows 上尤其昂贵,且模型手写 HTTP 请求错误率高
2. **结果不可结构化**——模型从网页 HTML 里提取型号、描述、数据手册地址,字段缺失/格式混乱是常态
3. **无法保证可设计性**——搜到的器件不一定有 EDA 模型(原理图符号 / PCB 封装),放进设计后发现无法布局连线
本插件封装芯灵 queryPage 搜索接口为一次函数调用,毫秒级返回结构化 JSON(mpn / 制造商 / 描述 / 数据手册),默认过滤出带 EDA 模型的器件,保证结果可直接用于 PCB 设计。
## 安全模型
- **白名单域名**:仅向写死的 `https://www.eda.cn/api/chiplet/products/queryPage` 发送 POST 请求,不接受用户传入的 URL
- **入口参数双重校验**:工具入口(`runSearch`)与 API 客户端(`queryPageSearch`)各自独立校验,不依赖上游 schema
- `keyword`:非空字符串,≤200 字符
- `page_size`:整数 1–50
- `require_eda_model`:布尔值
- **HTTP 状态码 + 业务 code 双重校验**:HTTP 200 不代表业务成功,必须再检查响应体 `code === 200000`(eda.cn 接口的坑,详见 [queryPage.ts](src/queryPage.ts) 文件头注释)
- **防御性结构解包**:对 `result[].queryPartVO.part` 做空值过滤,避免下游 `map` 时 `undefined` 报错
- **字段白名单**:返回只取 `mpn` / `manufacturer_id` / `part_desc` / `datasheet` 四个字段,不透传接口原始返回的其他字段
- **超时兜底**:`timeoutMs: 15000`(网络请求,高于纯计算工具的 1000ms)
- 工具参数会记入会话日志,不要传入敏感数据
## 架构
```
┌──────────────────────────────────────┐
│ DSH Agent │
│ tool call: pcb_parts_search { ... } │
└──────────────┬───────────────────────┘
│ ctx.tools.register()
┌──────────────▼───────────────────────┐
│ src/index.ts │
│ Cordis 插件入口 │
│ runSearch() → queryPageSearch() │
│ renderResults() → 文本块 │
└──────────────┬───────────────────────┘
│
┌──────────────▼───────────────────────┐
│ src/queryPage.ts │
│ fetch(SEARCH_URL, POST) │
│ HTTP 校验 → code 校验 → 结构拍平 │
└──────────────────────────────────────┘
```
- `src/index.ts`:Cordis 插件入口(`name`/`inject`/`apply`),注册 `pcb_parts_search` 工具;含参数防御、结果映射、文本渲染
- `src/queryPage.ts`:`queryPageSearch(keyword, options): Promise<QueryPagePart[]>`——请求 eda.cn 接口,校验 HTTP + 业务 code,拍平嵌套结构
- `src/invariant.ts`:不变量伴随插件(无运行时不变量,行为由测试覆盖)
## 工具声明
注册 `pcb_parts_search` 工具(`@deepseek-ai/dsh-tool-pcb-parts-search`,row id `tool-pcb-parts-search`),输出 JSON 文本字符串。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `keyword` | string | ✅ | 搜索关键词:型号(如 `"STM32F103C8T6"`)、描述(如 `"32-bit microcontroller 72MHz"`)或组合值(如 `"0402 10k resistor"`)。≤200 字符。模糊匹配,可能返回型号相近的候选 |
| `page_size` | integer | | 最多返回条数,范围 1–50,默认 5。选型用 5–10 即可;广泛对比可调大 |
| `require_eda_model` | boolean | | 是否只返回有 EDA 模型(原理图符号 + PCB 封装)的器件,默认 `true`。仅做调研不需要布局时设 `false` |
## 返回格式
JSON 数组,每项结构如下:
```json
[
{
"mpn": "STM32F103C8T6",
"mfgid": "8598",
"description": "ARM Cortex-M3 32位微控制器 72MHz 64KB Flash LQFP-48",
"datasheet": "//file.eda.cn/web2/M00/1B/31/pYYBAGGCZMuAXwY2AAV0cV9Yibc636.pdf"
}
]
```
渲染输出(给对话 UI 展示):
```
1. STM32F103C8T6 (mfgid: 8598) — ARM Cortex-M3 32位微控制器 72MHz 64KB Flash LQFP-48
datasheet: https://file.eda.cn/web2/M00/1B/31/pYYBAGGCZMuAXwY2AAV0cV9Yibc636.pdf
```
> `datasheet` 字段可能是协议相对 URL(`//` 开头),渲染时自动补 `https:` 前缀。
## 示例
```
pcb_parts_search { keyword: "STM32F103C8T6" }
→ [{ "mpn": "STM32F103C8T6", "mfgid": "8598", "description": "...", "datasheet": "..." }]
pcb_parts_search { keyword: "0402 10k resistor", page_size: 10 }
→ [{ "mpn": "RK73H1JTTD1003F", "mfgid": "8598", "description": "0402 10kΩ ±1% 贴片电阻", "datasheet": "..." }, ...]
pcb_parts_search { keyword: "LM358", require_eda_model: false }
→ [{ "mpn": "LM358", "mfgid": "...", "description": "双运算放大器", "datasheet": "..." }, ...]
```
## 边界行为
| 情况 | 处理 |
|---|---|
| 空关键词 | 报错:`pcb_parts_search: keyword cannot be empty` |
| 关键词 >200 字符 | 报错:`pcb_parts_search: keyword too long (N > 200)` |
| `page_size` 非整数或超出 1–50 | 报错:`pcb-parts-search: pageSize must be an integer between 1 and 50` |
| `page_size` 非数字 | 回退默认值 5 |
| `require_eda_model` 非布尔 | 回退默认值 `true` |
| HTTP 非 200 | 报错:`pcb-parts-search: HTTP <status>` |
| 业务 `code !== 200000` | 报错:`pcb-parts-search: 接口返回异常: <code> <message>` |
| `result` 数组为空 | 返回空数组 `[]`,渲染输出 `No PCB parts matched the search criteria.` |
| `result[].queryPartVO.part` 为 null | 过滤掉该项,不报错 |
| 器件字段缺失 | 回退为空串 `""`,不出现 `undefined` |
| datasheet 为协议相对 URL | 渲染时补 `https:` 前缀;JSON 输出保留原始值 |
| 网络超时 | 15s 后工具超时,由 DSH 超时机制处理 |
## 关键词搜索 vs 精确查询
queryPage 的 `desc` 字段是**模糊关键词匹配**,不是 MPN 精确查询。传入 MPN 当关键词能搜到候选列表,但列表里可能混入型号相近的其他器件,顺序也不保证"精确匹配排最前"。需要精确定位到某一条时,调用方需自行在返回结果里按 `mpn`(建议大小写不敏感)+ `mfgid` 做二次过滤。
## npm 0.1.0-rc.6 兼容
本插件遵循 DSH 0.1.0-rc.6(npm)依赖线:
- **类型/运行时**:`@deepseek-ai/cordis: ^4.0.1` + `@deepseek-ai/dsh-tools: >=0.0.1-rc.1 <0.2.0` + `@deepseek-ai/dsh-invariants: >=0.0.1-rc.1 <0.2.0`(peer)
- **独立构建**:`npm install`(devDependencies 自包含 typescript/vitest/@types/node)→ `npm run typecheck` → `npm test` → `npm run build` → `npm pack`
- **bundle 声明**:`package.json` 的 `dsh.bundle.patch`(指向 `cordis.patch.yml`)+ `exports` 导出
- **patch 格式**:`cordis.patch.yml` 使用 `- insert:` 列表(DSH 0.1.0-rc.6 的 patch 是 id-targeted 语义,裸 `- id:` 条目会报 `entry not found`)
- **files**:发布 tarball 含 `lib/`、`src/`、`cordis.patch.yml`
## 安装
### Profile Bundle(推荐)
```sh
# 交互式(web)profile
dsh plugin --profile web add <repo-or-tarball>
# 一次性任务(headless)profile —— dsh run 默认使用 headless
dsh plugin --profile headless add <repo-or-tarball>
```
也可以先用 `npm pack` 打出 tarball 再安装:
```sh
cd dsh-pcb-parts-search
npm install && npm pack
dsh plugin --profile web add ./deepseek-ai-dsh-tool-pcb-parts-search-*.tgz
dsh plugin --profile headless add ./deepseek-ai-dsh-tool-pcb-parts-search-*.tgz
```
包内 `dsh.bundle.patch`(指向 `cordis.patch.yml`)会在安装后自动把插件加入 profile 的 layer stack(row id:`tool-pcb-parts-search`)。插件缺失的 peer 依赖(`@deepseek-ai/cordis`、`@deepseek-ai/dsh-tools`、`@deepseek-ai/dsh-invariants`)由 profile 的 healed `profiles/node_modules` 回退安装提供。
> ⚠️ web 与 headless 是**不同 profile**:web 安装不会自动覆盖 headless;`dsh run` 默认使用 headless profile。Windows 路径使用正斜杠(`C:/...`)。
### 验证安装
```sh
dsh --profile web --dump-config | grep tool-pcb-parts-search
```
### 运行验证
```sh
dsh run "使用 pcb_parts_search 工具搜索 STM32F103C8T6"
```
### 源码开发依赖链接
本插件 peer 依赖来自 DSH monorepo。源码开发时需链接依赖:
```sh
# Windows (PowerShell)
New-Item -ItemType Junction -Path "node_modules\cordis" -Target "C:\code\deepseek-harness\vendor\cordis" -Force
New-Item -ItemType Junction -Path "node_modules\@deepseek-ai\dsh-tools" -Target "C:\code\deepseek-harness\packages\core\tools" -Force
New-Item -ItemType Junction -Path "node_modules\@deepseek-ai\dsh-invariants" -Target "C:\code\deepseek-harness\packages\runtime-diagnostics\invariants" -Force
```
## 用法
安装后,agent 自动获得 `pcb_parts_search` 工具:
```
pcb_parts_search { keyword: "STM32F103C8T6", page_size: 10 } → [{ "mpn": "...", ... }]
```
工具名满足 DeepSeek 函数名约束(≤64 字符,`[A-Za-z0-9_-]`)。注册后自动进入 Code Mode SDK(`await tools.pcb_parts_search(...)`),canonical 返回值为 JSON 文本字符串。
## 已知限制
1. **仅支持关键词搜索**:queryPage 的 `desc` 是模糊匹配,不是 MPN 精确查询;需要精确定位时调用方需自行二次过滤
2. **数据源单一**:仅查询芯灵 eda.cn,不聚合 DigiKey / Mouser / LCSC 等其他元器件平台
3. **需要网络访问**:工具会向 `www.eda.cn` 发送 HTTPS 请求,离线环境不可用
4. **接口可用性依赖第三方**:eda.cn 服务不可用时工具会报错,无降级策略
5. **返回字段有限**:只取 mpn / mfgid / description / datasheet,不包含库存、价格、封装尺寸等采购信息
## 测试
```bash
npm test
```
- `register.spec.ts`:注册契约(AUDIT-CROSS-02 风格)——验证插件导出 `name`/`inject`/`apply`、工具注册名 `pcb_parts_search`、参数 schema、render 函数、timeout 配置
## 许可
MIT
Install
dsh plugin --profile web add github:Huaqiu-Electronics/dsh-pcb-parts-search
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install deepseek-ai-dsh-tool-pcb-parts-search from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.