Files
dsh-enhancements/plugins/dsh-usage/host.js
T
江晨 fdafd5d6b3 chore: 初始化 dsh-enhancements 留档仓库
- 插件源码:dsh-usage(用户头像 + DeepSeek 官方 API 消耗面板)
- 工具:dl-gh.mjs(node fetch 下载 gh,绕开沙箱 curl 限制)
- 文档:PLAN.md 路线图 + mmx 视觉桥接补丁说明
- 资产:DeepSeek 鲸鱼图标
2026-08-17 11:54:40 +08:00

48 lines
2.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// dsh-usage 插件 — Host 半
// 通过 cordis_define 定义(动态 Cordis 插件)。
// 提供两个 Package-private RPC
// usage/balance — 读取 %DSH_HOME%\.credentials.yaml 的 DEEPSEEK_API_KEY
// 调用 DeepSeek 官方余额 APIGET /user/balance),返回 JSON。
// usage/openPortal— 用系统默认浏览器打开官网用量页。
// 密钥只在 node 子进程内读取与使用,绝不打印、不入库。
return {
inject: ['shell'],
apply(ctx) {
harness.handle('usage/balance', async (args) => {
const script = [
"const fs = require('node:fs');",
"const os = require('node:os');",
"const path = require('node:path');",
"const home = process.env.DSH_HOME || path.join(os.homedir(), '.dsh');",
"const file = path.join(home, '.credentials.yaml');",
"let key = null;",
"try { const txt = fs.readFileSync(file, 'utf8'); const m = txt.match(/DEEPSEEK_API_KEY:\\s*(\\S+)/); if (m) key = m[1]; } catch (e) {}",
"if (!key) { console.log(JSON.stringify({ error: 'no-api-key', file: file })); process.exit(0); }",
"fetch('https://api.deepseek.com/user/balance', { headers: { Authorization: 'Bearer ' + key, Accept: 'application/json' }, signal: AbortSignal.timeout(15000) })",
" .then(r => r.json().then(j => console.log(JSON.stringify(Object.assign({ status: r.status }, j)))))",
" .catch(e => console.log(JSON.stringify({ error: String((e && e.message) || e) })));",
].join('\n')
try {
const spec = ctx.shell.resolve({ command: 'node', args: ['-e', script] })
const res = await ctx.shell.run(spec)
const stdout = String(res.stdout || '')
const lines = stdout.trim().split(/\r?\n/).filter(Boolean)
if (lines.length) return JSON.parse(lines[lines.length - 1])
return { error: 'empty-output', stderr: String(res.stderr || '').slice(0, 400) }
} catch (e) {
return { error: String((e && e.message) || e) }
}
})
harness.handle('usage/openPortal', async () => {
try {
const spec = ctx.shell.resolve({ command: 'cmd', args: ['/c', 'start', '', 'https://platform.deepseek.com/usage'] })
await ctx.shell.run(spec)
return { ok: true }
} catch (e) {
return { ok: false, error: String((e && e.message) || e) }
}
})
},
}