dsh-opencode-usage-dashboard 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -17
- package/client.js +963 -166
- package/package.json +1 -1
- package/start.mjs +37 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-opencode-usage-dashboard",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OpenCode 用量面板:在 DeepSeek Harness 侧栏查看 Go 订阅额度、Console 按量花费、用量趋势与月度预测。OpenCode quota, spend, usage and forecast dashboard for DeepSeek Harness.",
|
|
6
6
|
"license": "MIT",
|
package/start.mjs
CHANGED
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
* 包名已从 @local/dsh-opencode-quota 迁移到 dsh-opencode-usage-dashboard;
|
|
10
10
|
* 脚本会顺手清理旧包名留下的依赖/junction。
|
|
11
11
|
*
|
|
12
|
+
* 不用先退出 DSH:`dsh plugin` 只是把参数转发给 profile 目录里的 pnpm,
|
|
13
|
+
* 安装动作和运行中的 DSH 不冲突。profile 的 base 层默认启用 `@deepseek-ai/dsh-hmr`
|
|
14
|
+
* (`root` 为空,只盯 profile manifest 与 patch 文件),插件管理器改完包会走
|
|
15
|
+
* `hmr.reconcileProfile()` 就地重新组合,所以 profile 一变 DSH 自己就会换。
|
|
16
|
+
* 只有 reconcile 报 no-hmr / package-moved / host-module 这类原因时才需要重启。
|
|
17
|
+
* 脚本因此不拦进程;真被文件占用(EBUSY/EPERM)时再提示退出 DSH 重跑。
|
|
18
|
+
*
|
|
12
19
|
* 为什么要先删目录:DSH 当前插件管理器卸载 `link:` 依赖时不会删除
|
|
13
20
|
* `node_modules` 里的 junction;直接 add 另一种来源会 EPERM。
|
|
14
21
|
*
|
|
@@ -93,7 +100,6 @@ async function chooseSource() {
|
|
|
93
100
|
const rl = createInterface({ input: process.stdin, output: process.stdout })
|
|
94
101
|
const state = installedState()
|
|
95
102
|
console.log(`当前安装:${currentLabel()}`)
|
|
96
|
-
console.log('切换前请先完全退出 DSH。')
|
|
97
103
|
console.log('')
|
|
98
104
|
console.log(` 1) 本地 link${state === 'link' ? '(当前)' : ''} ${repoRoot}`)
|
|
99
105
|
console.log(` 2) GitHub${state === 'github' ? '(当前)' : ''} ${REPO_SPEC}`)
|
|
@@ -117,16 +123,19 @@ if (state === source) {
|
|
|
117
123
|
console.log(`当前已经是${stateLabel(state)},将重新安装。`)
|
|
118
124
|
}
|
|
119
125
|
|
|
120
|
-
|
|
126
|
+
/** DSH 是否在跑:只用来决定结尾提示什么,不阻止安装。 */
|
|
127
|
+
function dshRunning() {
|
|
128
|
+
if (process.platform !== 'win32') {
|
|
129
|
+
const check = spawnSync('pgrep', ['-f', 'DeepSeek Harness|dsh (web|desktop)'], { encoding: 'utf8' })
|
|
130
|
+
return check.status === 0 && (check.stdout || '').trim() !== ''
|
|
131
|
+
}
|
|
121
132
|
const check = spawnSync('tasklist', ['/FI', 'IMAGENAME eq DeepSeek Harness.exe', '/NH'], {
|
|
122
133
|
encoding: 'utf8',
|
|
123
134
|
windowsHide: true,
|
|
124
135
|
})
|
|
125
|
-
|
|
126
|
-
console.error('DSH 还在运行。请先完全退出 DeepSeek Harness,再运行本脚本。')
|
|
127
|
-
process.exit(1)
|
|
128
|
-
}
|
|
136
|
+
return check.status === 0 && /DeepSeek Harness\.exe/i.test(check.stdout || '')
|
|
129
137
|
}
|
|
138
|
+
const dshLive = dshRunning()
|
|
130
139
|
|
|
131
140
|
/** 用当前平台的 shell 调用 dsh plugin。 */
|
|
132
141
|
function runDsh(args, childEnv = process.env) {
|
|
@@ -173,6 +182,9 @@ function removeTemps(dir) {
|
|
|
173
182
|
|
|
174
183
|
console.log('')
|
|
175
184
|
console.log(`目标:${source === 'github' ? 'GitHub 版' : '本地 link 版'}(${PACKAGE_NAME})`)
|
|
185
|
+
if (dshLive) {
|
|
186
|
+
console.log('DSH 正在运行:安装不受影响,profile 一变它会自己重新组合插件。')
|
|
187
|
+
}
|
|
176
188
|
|
|
177
189
|
console.log('[1/3] 卸载当前版本…')
|
|
178
190
|
const deps = dependencyNames()
|
|
@@ -196,10 +208,19 @@ console.log('[2/3] 清理 node_modules 残留…')
|
|
|
196
208
|
if (pathState(oldPkgDir) !== 'none' && pathState(pkgDir) === 'none') {
|
|
197
209
|
console.log(`检测到旧包名 ${OLD_PACKAGE_NAME},清理后会安装 ${PACKAGE_NAME}。`)
|
|
198
210
|
}
|
|
199
|
-
|
|
200
|
-
removeInstalled(
|
|
201
|
-
|
|
202
|
-
removeTemps(
|
|
211
|
+
try {
|
|
212
|
+
removeInstalled(pkgDir)
|
|
213
|
+
removeInstalled(oldPkgDir)
|
|
214
|
+
removeTemps(nodeModulesDir)
|
|
215
|
+
removeTemps(oldLocalDir)
|
|
216
|
+
} catch (error) {
|
|
217
|
+
if (error && ['EPERM', 'EBUSY', 'ENOTEMPTY', 'EACCES'].includes(error.code)) {
|
|
218
|
+
console.error(`清理失败(${error.code}):${error.path || '目录'} 正被占用。`)
|
|
219
|
+
if (dshLive) console.error('请退出 DSH 后重跑本命令;如果仍失败,手动删掉上面这个路径。')
|
|
220
|
+
process.exit(1)
|
|
221
|
+
}
|
|
222
|
+
throw error
|
|
223
|
+
}
|
|
203
224
|
|
|
204
225
|
/** 中断的插件操作会留下 run.json,清掉避免下次被当成“操作进行中”。 */
|
|
205
226
|
console.log('清理 plugin-manager 运行标记…')
|
|
@@ -226,9 +247,14 @@ if (result.error) {
|
|
|
226
247
|
}
|
|
227
248
|
if (result.status !== 0) {
|
|
228
249
|
console.error(`dsh plugin 退出码 ${result.status}`)
|
|
250
|
+
if (dshLive) console.error('如果上面是 EBUSY/EPERM,说明 DSH 正在占用目录:退出 DSH 后重跑本命令。')
|
|
229
251
|
process.exit(result.status || 1)
|
|
230
252
|
}
|
|
231
253
|
|
|
232
254
|
console.log('')
|
|
233
255
|
console.log(`完成:profile "${profile}" 现在使用 ${source === 'github' ? 'GitHub 版' : '本地 link 版'}(${PACKAGE_NAME})。`)
|
|
234
|
-
|
|
256
|
+
if (dshLive) {
|
|
257
|
+
console.log('DSH 会按新 profile 重新组合;如果它提示「请重启 DSH 使更改生效」再重启。')
|
|
258
|
+
} else {
|
|
259
|
+
console.log('启动 DSH 即可。')
|
|
260
|
+
}
|