- 插件源码:dsh-usage(用户头像 + DeepSeek 官方 API 消耗面板) - 工具:dl-gh.mjs(node fetch 下载 gh,绕开沙箱 curl 限制) - 文档:PLAN.md 路线图 + mmx 视觉桥接补丁说明 - 资产:DeepSeek 鲸鱼图标
48 lines
2.4 KiB
JavaScript
48 lines
2.4 KiB
JavaScript
// dsh-usage 插件 — Host 半
|
||
// 通过 cordis_define 定义(动态 Cordis 插件)。
|
||
// 提供两个 Package-private RPC:
|
||
// usage/balance — 读取 %DSH_HOME%\.credentials.yaml 的 DEEPSEEK_API_KEY,
|
||
// 调用 DeepSeek 官方余额 API(GET /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) }
|
||
}
|
||
})
|
||
},
|
||
}
|