# Trajectory: 汇率换算(真实网络请求 + 挂载失败自修复)
真实 E2E 会话记录(`dsh web` RPC 驱动,DeepSeek-V4-Flash,未经剪辑;从 session.history 事件流提取)。
**用户输入:**
> 供应商报价 12800 美元,折人民币大概多少?我做跨境采购,天天都要算这种汇率换算,欧元日元也常用,最好以后能直接算
### step 1 · 🔧 `todo_write` {"todos": [{"content": "拉取实时汇率并算出 12800 美元 ≈ 人民币", "status": "in_progress"}, {"content": "创建持久化汇率换算工具(evolution),支持 USD/CNY/EUR/JPY 等", "status": "pending"}, {"content": "用新工具复算并验证,向用户汇报", "status": "pending"}]}
```
Updated todo list: 2 pending, 1 in progress, 0 completed.
```
### step 1 · 🔧 `bash` {"command": "curl -s --max-time 15 https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/usd.json | node -e \"let d='';process.stdin.on('data',c=>d+=c).on('end',()=>{const j=JSON.parse(d);console.log('rate date:',j.date);for(const c of ['cny','eur','jpy'])console.log('USD->'+c+':',j.usd[c]);console.log('12800 USD in CNY:',(12800*j.usd.cny).toFixed(2));console.log('12800 USD in EUR:',(12800*j.usd.eur).toFixed(2));console.log('12800 USD in JPY:',Math.round(12800*j.usd.jpy))})…
```
rate date: 2026-08-05
USD->cny: 6.74778734
USD->eur: 0.86675437
USD->jpy: 157.41902346
12800 USD in CNY: 86371.68
12800 USD in EUR: 11094.46
12800 USD in JPY: 2014964
```
拿到实时汇率了(12800 美元 ≈ **86,372 元人民币**)。现在给你做一个持久化的汇率换算工具,以后直接说"12800 美元折人民币""5000 欧元折日元"就能算:
### step 2 · 🔧 `evolve_add` {"name": "currency-converter", "description": "实时汇率换算工具,支持 USD/CNY/EUR/JPY 等 150+ 币种,跨境采购报价换算直接用"}
模型现场编写的插件源码(source 参数)
```js
import { defineTool } from '@deepseek-ai/dsh-tools'
export const name = 'currency-converter'
export const inject = ['tools']
const FALLBACK_BASE = 'https://open.er-api.com/v6/latest'
async function fetchRates(base) {
// Primary: fawazahmed0 currency-api (free, no key, per-base rates)
try {
const url = `https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/${base.toLowerCase()}.json`
const res = await fetch(url, { signal: AbortSignal.timeout(12000) })
if (!res.ok) throw new Error(`status ${res.status}`)
const data = await res.json()
return { date: data.date, rates: data[base.toLowerCase()] }
} catch (err) {
// Fallback: open.er-api.com (USD-anchored, computes cross rates)
const res = await fetch(`${FALLBACK_BASE}/${base.toUpperCase()}`, { signal: AbortSignal.timeout(12000) })
if (!res.ok) throw new Error(`fallback failed: ${err.message}; status ${res.status}`)
const data = await res.json()
if (data.result !== 'success') throw new Error(`rate API error: ${data['error-type'] || 'unknown'}`)
return { date: data.time_last_update_utc, rates: data.conversion_rates }
}
}
export function apply(ctx) {
ctx.tools.register(defineTool({
name: 'convert_currency',
description: '按实时汇率换算金额,支持 150+ 币种(ISO 4217 代码,如 USD、CNY、EUR、JPY、GBP、HKD、KRW)。跨境采购/报价折算必备:'convert_currency(12800, "USD", "CNY")''、一次算多币种 'convert_currency(5000, "EUR", "CNY,JPY,USD")'。',
parameters: {
amount: { type: 'number', required: true, description: '要换算的金额(源币种金额)。' },
from: { type: 'string', required: true, description: '源币种 ISO 4217 代码,如 USD、EUR、JPY、CNY。' },
to: { type: 'string', required: true, description: '目标币种代码,多个用逗号分隔,如 "CNY" 或 "CNY,EUR,JPY"。' },
},
output: {
schema: {
type: 'object',
properties: {
from: { type: 'string' },
amount: { type: 'number' },
date: { type: 'string' },
results: {
type: 'array',
items: {
type: 'object',
properties: {
currency: { type: 'string' },
rate: { type: 'number' },
converted: { type: 'number' },
rounded: { type: 'number' },
},
},
},
},
},
render: (_args, value) => {
const parts = value.results.map(r =>
`${r.currency.toUpperCase()} ${r.rounded.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}(汇率 ${r.rate.toFixed(4)})`
)
return [{
type: 'text',
text: `${value.amount.toLocaleString('zh-CN')} ${value.from.toUpperCase()} ≈ ${parts.join(';')}(数据日期 ${value.date})`,
}]
},
},
async execute(args) {
const targets = String(args.to).split(',').map(s => s.trim().toUpperCase()).filter(Boolean)
if (!targets.length) throw new Error('to 至少需要一个币种代码')
const data = await fetchRates(args.from)
const results = targets.map(code => {
const rate = data.rates[code.toUpperCase()] ?? data.rates[code.toLowerCase()]
if (rate == null) throw new Error(`未找到 ${code} 的汇率`)
const converted = args.amount * rate
return {
currency: code,
rate,
converted,
rounded: Math.round(converted * 100) / 100,
}
})
return { from: String(args.from).toUpperCase(), amount: args.amount, date: data.date, results }
},
}))
}
```
```
Error: evolution "currency-converter" failed to mount: Unexpected identifier 'convert_currency'
The source is kept at /Users/jinqiu/.dsh/evolve/currency-converter.mjs but not persisted to the manifest — fix it and call evolve_add again with the same name.
```
描述字符串里的引号没转义,修一下重新挂载:
### step 3 · 🔧 `evolve_add` {"description": "实时汇率换算工具,支持 USD/CNY/EUR/JPY 等 150+ 币种,跨境采购报价换算直接用", "name": "currency-converter"}
模型现场编写的插件源码(source 参数)
```js
import { defineTool } from '@deepseek-ai/dsh-tools'
export const name = 'currency-converter'
export const inject = ['tools']
const FALLBACK_BASE = 'https://open.er-api.com/v6/latest'
async function fetchRates(base) {
// Primary: fawazahmed0 currency-api (free, no key, per-base rates)
try {
const url = `https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/${base.toLowerCase()}.json`
const res = await fetch(url, { signal: AbortSignal.timeout(12000) })
if (!res.ok) throw new Error(`status ${res.status}`)
const data = await res.json()
return { date: data.date, rates: data[base.toLowerCase()] }
} catch (err) {
// Fallback: open.er-api.com (USD-anchored, computes cross rates)
const res = await fetch(`${FALLBACK_BASE}/${base.toUpperCase()}`, { signal: AbortSignal.timeout(12000) })
if (!res.ok) throw new Error(`fallback failed: ${err.message}; status ${res.status}`)
const data = await res.json()
if (data.result !== 'success') throw new Error(`rate API error: ${data['error-type'] || 'unknown'}`)
return { date: data.time_last_update_utc, rates: data.conversion_rates }
}
}
export function apply(ctx) {
ctx.tools.register(defineTool({
name: 'convert_currency',
description: '按实时汇率换算金额,支持 150+ 币种(ISO 4217 代码,如 USD、CNY、EUR、JPY、GBP、HKD、KRW)。跨境采购报价折算必备:例如 convert_currency(12800, "USD", "CNY"),或一次算多币种 convert_currency(5000, "EUR", "CNY,JPY,USD")。',
parameters: {
amount: { type: 'number', required: true, description: '要换算的金额(源币种金额)。' },
from: { type: 'string', required: true, description: '源币种 ISO 4217 代码,如 USD、EUR、JPY、CNY。' },
to: { type: 'string', required: true, description: '目标币种代码,多个用逗号分隔,如 "CNY" 或 "CNY,EUR,JPY"。' },
},
output: {
schema: {
type: 'object',
properties: {
from: { type: 'string' },
amount: { type: 'number' },
date: { type: 'string' },
results: {
type: 'array',
items: {
type: 'object',
properties: {
currency: { type: 'string' },
rate: { type: 'number' },
converted: { type: 'number' },
rounded: { type: 'number' },
},
},
},
},
},
render: (_args, value) => {
const parts = value.results.map(r =>
`${r.currency.toUpperCase()} ${r.rounded.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}(汇率 ${r.rate.toFixed(4)})`
)
return [{
type: 'text',
text: `${value.amount.toLocaleString('zh-CN')} ${value.from.toUpperCase()} ≈ ${parts.join(';')}(数据日期 ${value.date})`,
}]
},
},
async execute(args) {
const targets = String(args.to).split(',').map(s => s.trim().toUpperCase()).filter(Boolean)
if (!targets.length) throw new Error('to 至少需要一个币种代码')
const data = await fetchRates(args.from)
const results = targets.map(code => {
const rate = data.rates[code.toUpperCase()] ?? data.rates[code.toLowerCase()]
if (rate == null) throw new Error(`未找到 ${code} 的汇率`)
const converted = args.amount * rate
return {
currency: code,
rate,
converted,
rounded: Math.round(converted * 100) / 100,
}
})
return { from: String(args.from).toUpperCase(), amount: args.amount, date: data.date, results }
},
}))
}
```
```
Error: evolution "currency-converter" failed to mount: unsupported JSON schema: schema.additionalProperties must be explicitly true or false
The source is kept at /Users/jinqiu/.dsh/evolve/currency-converter.mjs but not persisted to the manifest — fix it and call evolve_add again with the same name.
```
输出 schema 需要显式声明 `additionalProperties`,补上再挂:
### step 4 · 🔧 `evolve_add` {"description": "实时汇率换算工具,支持 USD/CNY/EUR/JPY 等 150+ 币种,跨境采购报价换算直接用", "name": "currency-converter"}
模型现场编写的插件源码(source 参数)
```js
import { defineTool } from '@deepseek-ai/dsh-tools'
export const name = 'currency-converter'
export const inject = ['tools']
const FALLBACK_BASE = 'https://open.er-api.com/v6/latest'
async function fetchRates(base) {
// Primary: fawazahmed0 currency-api (free, no key, per-base rates)
try {
const url = `https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/${base.toLowerCase()}.json`
const res = await fetch(url, { signal: AbortSignal.timeout(12000) })
if (!res.ok) throw new Error(`status ${res.status}`)
const data = await res.json()
return { date: data.date, rates: data[base.toLowerCase()] }
} catch (err) {
// Fallback: open.er-api.com (USD-anchored, computes cross rates)
const res = await fetch(`${FALLBACK_BASE}/${base.toUpperCase()}`, { signal: AbortSignal.timeout(12000) })
if (!res.ok) throw new Error(`fallback failed: ${err.message}; status ${res.status}`)
const data = await res.json()
if (data.result !== 'success') throw new Error(`rate API error: ${data['error-type'] || 'unknown'}`)
return { date: data.time_last_update_utc, rates: data.conversion_rates }
}
}
export function apply(ctx) {
ctx.tools.register(defineTool({
name: 'convert_currency',
description: '按实时汇率换算金额,支持 150+ 币种(ISO 4217 代码,如 USD、CNY、EUR、JPY、GBP、HKD、KRW)。跨境采购报价折算必备:例如 convert_currency(12800, "USD", "CNY"),或一次算多币种 convert_currency(5000, "EUR", "CNY,JPY,USD")。',
parameters: {
amount: { type: 'number', required: true, description: '要换算的金额(源币种金额)。' },
from: { type: 'string', required: true, description: '源币种 ISO 4217 代码,如 USD、EUR、JPY、CNY。' },
to: { type: 'string', required: true, description: '目标币种代码,多个用逗号分隔,如 "CNY" 或 "CNY,EUR,JPY"。' },
},
output: {
schema: {
type: 'object',
additionalProperties: false,
properties: {
from: { type: 'string' },
amount: { type: 'number' },
date: { type: 'string' },
results: {
type: 'array',
items: {
type: 'object',
additionalProperties: false,
properties: {
currency: { type: 'string' },
rate: { type: 'number' },
converted: { type: 'number' },
rounded: { type: 'number' },
},
},
},
},
},
render: (_args, value) => {
const parts = value.results.map(r =>
`${r.currency.toUpperCase()} ${r.rounded.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}(汇率 ${r.rate.toFixed(4)})`
)
return [{
type: 'text',
text: `${value.amount.toLocaleString('zh-CN')} ${value.from.toUpperCase()} ≈ ${parts.join(';')}(数据日期 ${value.date})`,
}]
},
},
async execute(args) {
const targets = String(args.to).split(',').map(s => s.trim().toUpperCase()).filter(Boolean)
if (!targets.length) throw new Error('to 至少需要一个币种代码')
const data = await fetchRates(args.from)
const results = targets.map(code => {
const rate = data.rates[code.toUpperCase()] ?? data.rates[code.toLowerCase()]
if (rate == null) throw new Error(`未找到 ${code} 的汇率`)
const converted = args.amount * rate
return {
currency: code,
rate,
converted,
rounded: Math.round(converted * 100) / 100,
}
})
return { from: String(args.from).toUpperCase(), amount: args.amount, date: data.date, results }
},
}))
}
```
```
Evolution "currency-converter" grown: active. Persisted at /Users/jinqiu/.dsh/evolve/currency-converter.mjs; new tools are callable from your next step.
```
工具挂载成功,现在用它来算:
### step 5 · 🔧 `convert_currency` {"amount": 12800, "from": "USD", "to": "CNY,EUR,JPY"}
```
12,800 USD ≈ CNY 86,371.68(汇率 6.7478);EUR 11,094.46(汇率 0.8668);JPY 2,014,963.5(汇率 157.4190)(数据日期 2026-08-05)
```
### step 6 · 🔧 `todo_write` {"todos": [{"content": "拉取实时汇率并算出 12800 美元 ≈ 人民币", "status": "completed"}, {"content": "创建持久化汇率换算工具(evolution),支持 USD/CNY/EUR/JPY 等", "status": "completed"}, {"content": "用新工具复算并验证,向用户汇报", "status": "completed"}]}
```
Updated todo list: 0 pending, 0 in progress, 3 completed.
```
算好了 ✅
## 12800 美元折人民币
按实时汇率(数据日期 2026-08-05,来源:fawazahmed0 currency-api / open.er-api):
| 币种 | 金额 | 汇率 |
|---|---|---|
| **CNY 人民币** | **≈ 86,372 元**(约 8.64 万) | 1 USD = 6.7478 |
| EUR 欧元 | ≈ 11,094 欧 | 1 USD = 0.8668 |
| JPY 日元 | ≈ 2,014,964 日元 | 1 USD = 157.42 |
⚠️ 采购提醒:这是**市场中间价**,实际到账一般按银行/平台的**买入卖出价**结算,通常会有 1~3% 的汇差和手续费,报价留预算余量时建议按 7.0 左右粗算(12800 × 7 ≈ **8.96 万**)。
## 以后直接算 ✅
我刚给本会话装了一个持久化的实时汇率换算工具(`currency-converter`,150+ 币种,双数据源自动容错),以后你直接说人话就行,比如:
- "**12800 美元折人民币多少**"
- "**5000 欧元折成日元和人民币**"
- "**报价 32000 港币,人民币多少钱**"
我会自动调用实时汇率换算,不用你记任何命令。这个能力跨会话保留,重启也还在;如果哪天不需要了,随时说一声"移除汇率工具"即可。