# Trajectory: 错误码查询(agent 主动自我进化)
真实 E2E 会话记录(`dsh web` RPC 驱动,DeepSeek-V4-Flash,未经剪辑;从 session.history 事件流提取)。
**用户输入:**
> E4103 是什么错误来着?另外我发现我每天都得来问你查错误码(表在 docs/error-codes.md 里),有没有办法让以后查起来快一点
### step 1 · 🔧 `glob` {"pattern": "docs/error-codes.md"}
```
docs/error-codes.md
```
### step 1 · 🔧 `bash` {"command": "pwd && ls", "description": "Show current directory and contents"}
```
/tmp/demo-shop
docs
```
### step 2 · 🔧 `read` {"file_path": "/tmp/demo-shop/docs/error-codes.md"}
```
/tmp/demo-shop/docs/error-codes.md
file
1: # demo-shop 错误码表
2:
3: | code | meaning | owner | retry |
4: |---|---|---|---|
5: | E4001 | 参数校验失败:缺少必填字段 | api-gw | no |
6: | E4102 | 库存不足,下单被拒 | inventory | no |
7: | E4103 | 库存服务超时(降级为预扣) | inventory | yes |
8: | E4201 | 支付渠道余额不足 | payment | no |
9: | E4202 | 支付网关限流 | payment | yes |
10: | E5001 | 订单状态机非法迁移 | order | no |
11: | E5102 | 优惠券已核销或过期 | promo | no |
(End of file - total 11 lines)
```
E4103 查到了——在 `docs/error-codes.md` 第 7 行:
| code | meaning | owner | retry |
|---|---|---|---|
| **E4103** | 库存服务超时(降级为预扣) | inventory | yes |
即:库存服务响应超时,系统已降级为"预扣"处理,属于 inventory 服务,**可以重试**。
至于"每天来问你查错误码"这个问题——正好可以给你建一个常驻的快速查询工具:我把查表逻辑做成一个持久化的能力挂载进来,以后你直接说"查 E4103"(或"查库存"这种关键词),我一步就能查出来,不用再翻文件。工具每次调用都实时解析 `docs/error-codes.md`,所以表里新增错误码后也自动生效,不用重新挂载。
现在挂载它:
### step 3 · 🔧 `evolve_add` {"name": "error-code-lookup", "description": "实时查询 demo-shop 错误码表(docs/error-codes.md),支持错误码或关键词检索,避免每次手动翻表。", "config": {"path": "/tmp/demo-shop/docs/error-codes.md"}}
模型现场编写的插件源码(source 参数)
```js
import { readFileSync, existsSync } from 'node:fs'
import { isAbsolute, resolve } from 'node:path'
import { defineTool } from '@deepseek-ai/dsh-tools'
export const name = 'error-code-lookup'
export const inject = ['tools']
const FALLBACKS = [
'/tmp/demo-shop/docs/error-codes.md',
'/private/tmp/demo-shop/docs/error-codes.md',
'docs/error-codes.md',
]
export function apply(ctx, config) {
const configured = config && config.path ? config.path : null
ctx.tools.register(defineTool({
name: 'lookup_error_code',
description: '查询 demo-shop 错误码表(docs/error-codes.md)。输入错误码(如 E4103)或关键词(如 库存 / 超时 / payment)即可返回 code、含义、owner、是否可重试;输入为空则列出全部。每次调用实时解析表文件,表格更新后无需重新挂载。',
parameters: {
code: { type: 'string', required: true, description: '错误码(如 E4103)或含义/owner 关键词;留空字符串可列出全部。' },
},
output: {
schema: { type: 'string' },
render: (_args, value) => [{ type: 'text', text: value }],
},
async execute(args) {
const file = resolveFile(configured)
if (!file) {
const tried = (configured ? [configured] : []).concat(FALLBACKS).join(', ')
return '未找到错误码表文件,尝试过:' + tried + '。可用 config.path 指定实际路径后重新挂载。'
}
const text = readFileSync(file, 'utf8')
const rows = parseTable(text)
const q = String(args.code == null ? '' : args.code).trim().toUpperCase()
const hits = q
? rows.filter((r) => r.code.toUpperCase() === q || r.meaning.toUpperCase().includes(q) || r.owner.toUpperCase().includes(q))
: rows
if (hits.length === 0) {
return '表内共 ' + rows.length + ' 条错误码,未匹配 "' + q + '"。可查看 ' + file + ' 确认是否已登记。'
}
const lines = hits.map((r) => r.code + ' | ' + r.meaning + ' | owner: ' + r.owner + ' | retry: ' + r.retry)
return '来源:' + file + '\n' + lines.join('\n')
},
}))
}
function resolveFile(configured) {
const candidates = []
if (configured) candidates.push(configured)
candidates.push(...FALLBACKS)
for (const c of candidates) {
const p = isAbsolute(c) ? c : resolve(process.cwd(), c)
if (existsSync(p)) return p
}
return null
}
function parseTable(text) {
const rows = []
for (const line of text.split('\n')) {
const t = line.trim()
if (!t.startsWith('|')) continue
if (/^\|[\s:|-]+\|$/.test(t)) continue
const cells = t.replace(/^\|/, '').replace(/\|$/, '').split('|').map((c) => c.trim())
if (cells.length < 4) continue
if (cells[0].toUpperCase() === 'CODE') continue
rows.push({ code: cells[0], meaning: cells[1], owner: cells[2], retry: cells[3] })
}
return rows
}
```
```
Evolution "error-code-lookup" grown: active. Persisted at /Users/jinqiu/.dsh/evolve/error-code-lookup.mjs; new tools are callable from your next step.
```
挂载成功。验证一下新工具是否正常工作:
### step 4 · 🔧 `lookup_error_code` {"code": "E4103"}
```
来源:/tmp/demo-shop/docs/error-codes.md
E4103 | 库存服务超时(降级为预扣) | owner: inventory | retry: yes
```
### step 4 · 🔧 `lookup_error_code` {"code": "库存"}
```
来源:/tmp/demo-shop/docs/error-codes.md
E4102 | 库存不足,下单被拒 | owner: inventory | retry: no
E4103 | 库存服务超时(降级为预扣) | owner: inventory | retry: yes
```
搞定,工具已生效并验证通过 ✅
**回到你的问题:**
**E4103** = 库存服务超时(降级为预扣),owner 是 inventory,**可重试**(retry: yes)。
**关于以后查得快一点:** 我给你装了一个常驻的 `lookup_error_code` 工具,刚刚已经挂载并实测可用:
- 以后你直接说 **"查 E4103"** 或 **"查库存"**(支持错误码或含义/owner 关键词),我一步就能返回结果,不用再手动翻 `docs/error-codes.md`;
- 它**每次调用都实时解析表文件**,所以你在表里新增错误码后立刻生效,不用重新配置;
- 这个能力是**持久化**的,重启会话后依然存在;
- 留空输入可以列出全部错误码。
刚才的实测结果:
- 查 `E4103` → `E4103 | 库存服务超时(降级为预扣) | owner: inventory | retry: yes`
- 查 `库存` → 同时返回 E4102、E4103 两条相关记录
一个小提醒:目前它指向 `/tmp/demo-shop/docs/error-codes.md`。如果以后这个表搬到别的地方,跟我说一声新路径,我用一条命令改一下配置即可。