@feiyang666/dsh-usage-plugin 1.13.1 → 1.14.1
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/CHANGELOG.md +42 -22
- package/README.md +11 -2
- package/README.zh.md +12 -2
- package/lib/client.js +352 -35
- package/lib/index.js +128 -39
- package/package.json +88 -88
package/lib/index.js
CHANGED
|
@@ -26,6 +26,22 @@ import {
|
|
|
26
26
|
resolveBalanceEndpoint
|
|
27
27
|
} from './balance.js'
|
|
28
28
|
|
|
29
|
+
// 周末统一按空闲价计费规则生效时间:北京时间 2026-08-23 00:00(周日)。
|
|
30
|
+
// 生效前(含周末)仍按原峰谷分段计费;生效后周末(周六、周日)全天统一按空闲价,工作日仍按峰谷分段。
|
|
31
|
+
export const WEEKEND_FLAT_AT = Date.parse('2026-08-23T00:00:00+08:00')
|
|
32
|
+
|
|
33
|
+
// 高峰时段判定:新规则(2026-08-23 起)周末(周六、周日)全天不再区分峰谷,统一按空闲价;
|
|
34
|
+
// 工作日仍按北京时间 9:00–12:00、14:00–18:00 为高峰;新规则生效前的调用仍按原规则判定。
|
|
35
|
+
// 星期取自平移后的北京时间(ts + 8h),避免 UTC 日历与北京日历在 16:00–24:00 UTC 段错位。
|
|
36
|
+
// 导出为独立函数,供 test/period.test.js 做回归测试(issue #9)。
|
|
37
|
+
export function isPeakAt(ts) {
|
|
38
|
+
const d = new Date(ts + 8 * 3600 * 1000)
|
|
39
|
+
const wd = d.getUTCDay() // 0=周日 1=周一 … 6=周六
|
|
40
|
+
if (ts >= WEEKEND_FLAT_AT && (wd === 0 || wd === 6)) return false
|
|
41
|
+
const t = d.getUTCHours() * 60 + d.getUTCMinutes()
|
|
42
|
+
return (t >= 9 * 60 && t < 12 * 60) || (t >= 14 * 60 && t < 18 * 60)
|
|
43
|
+
}
|
|
44
|
+
|
|
29
45
|
export default {
|
|
30
46
|
inject: ['fs', 'webServer', 'subprocess', 'credentials', 'settings', 'sandboxPolicy', 'agents'],
|
|
31
47
|
apply(ctx) {
|
|
@@ -86,9 +102,9 @@ export default {
|
|
|
86
102
|
// 新价格表(峰谷价)生效时间:北京时间 2026-08-17 00:00。
|
|
87
103
|
// 在此之前的调用按旧价格表(基础价 base)计费;之后按新价格表(峰谷价)计费。
|
|
88
104
|
const EFFECTIVE_AT = Date.parse('2026-08-17T00:00:00+08:00')
|
|
89
|
-
|
|
90
|
-
//
|
|
91
|
-
const
|
|
105
|
+
|
|
106
|
+
// 高峰/空闲判定使用模块级 isPeakAt(含周末规则与生效时间保护;实现见文件顶部导出,供回归测试)
|
|
107
|
+
const isPeak = isPeakAt
|
|
92
108
|
|
|
93
109
|
function modelKey(model) {
|
|
94
110
|
const m = String(model || '').toLowerCase()
|
|
@@ -98,16 +114,6 @@ export default {
|
|
|
98
114
|
return 'unknown'
|
|
99
115
|
}
|
|
100
116
|
|
|
101
|
-
// 高峰时段判定:新规则(2026-08-23 起)周末(周六、周日)全天不再区分峰谷,统一按空闲价;
|
|
102
|
-
// 工作日仍按北京时间 9:00–12:00、14:00–18:00 为高峰;新规则生效前的调用仍按原规则判定。
|
|
103
|
-
function isPeak(ts) {
|
|
104
|
-
const d = new Date(ts + 8 * 3600 * 1000)
|
|
105
|
-
const wd = d.getUTCDay() // 0=周日 1=周一 … 6=周六
|
|
106
|
-
if (ts >= WEEKEND_FLAT_AT && (wd === 0 || wd === 6)) return false
|
|
107
|
-
const t = d.getUTCHours() * 60 + d.getUTCMinutes()
|
|
108
|
-
return (t >= 9 * 60 && t < 12 * 60) || (t >= 14 * 60 && t < 18 * 60)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
117
|
// Third-party providers are priced only when a verified provider/model
|
|
112
118
|
// mapping exists. Unknown mappings deliberately remain zero rather than
|
|
113
119
|
// inheriting DeepSeek prices from a similar model name.
|
|
@@ -161,6 +167,52 @@ export default {
|
|
|
161
167
|
return (hit * p.cacheHit + miss * p.cacheMiss + out * p.output) / 1e6
|
|
162
168
|
}
|
|
163
169
|
|
|
170
|
+
// 过滤内部/占位调用(如 harness 内部 dsh2shell-* + model "fake"):
|
|
171
|
+
// 这些不是用户调用的 API 服务商,不出现在用量明细 / 消耗明细 / 日历统计里。
|
|
172
|
+
function isRealCall(rec) {
|
|
173
|
+
const model = String(rec.model || '').trim().toLowerCase()
|
|
174
|
+
const provider = String(rec.provider || '').trim().toLowerCase()
|
|
175
|
+
if (!model || model === 'fake' || model === 'unknown') return false
|
|
176
|
+
if (!provider || provider === 'unknown') return false
|
|
177
|
+
// 内部 agent/工具路由(dsh2shell-* 等)不计入用户可见明细
|
|
178
|
+
if (provider.indexOf('dsh') === 0) return false
|
|
179
|
+
return true
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// 把一条记录投影为 API 响应形状(供 list / tokenForMessage 共用,含成本与峰谷判定)。
|
|
183
|
+
function projectRecord(r) {
|
|
184
|
+
return {
|
|
185
|
+
time: r.time, model: r.model, provider: r.provider, purpose: r.purpose, sessionId: r.sessionId || '',
|
|
186
|
+
inputTokens: r.inputTokens, outputTokens: r.outputTokens,
|
|
187
|
+
cacheReadTokens: r.cacheReadTokens, cacheWriteTokens: r.cacheWriteTokens,
|
|
188
|
+
reasoningTokens: r.reasoningTokens, finishReason: r.finishReason,
|
|
189
|
+
interrupted: !!r.interrupted,
|
|
190
|
+
usdCnyRate: r.usdCnyRate || 0, fxDate: r.fxDate || '',
|
|
191
|
+
modelKey: modelKey(r.model),
|
|
192
|
+
baseCost: costFor(r, 'base'), peakValleyCost: costFor(r, 'peakValley'), autoCost: costFor(r, 'auto'),
|
|
193
|
+
peak: isPeak(r.time)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// 对已投影的记录做聚合(对话累计 / 本轮明细共用)。
|
|
198
|
+
function computeAgg(items) {
|
|
199
|
+
const agg = { calls: items.length, input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0, peakCost: 0, offCost: 0, baseCost: 0, totalCost: 0, hitRate: 0 }
|
|
200
|
+
let firstTime = 0, lastTime = 0
|
|
201
|
+
for (const it of items) {
|
|
202
|
+
agg.input += it.inputTokens; agg.output += it.outputTokens
|
|
203
|
+
agg.cacheRead += it.cacheReadTokens; agg.cacheWrite += it.cacheWriteTokens
|
|
204
|
+
agg.reasoning += it.reasoningTokens
|
|
205
|
+
if (it.peak) agg.peakCost += it.peakValleyCost; else agg.offCost += it.peakValleyCost
|
|
206
|
+
agg.baseCost += it.baseCost; agg.totalCost += it.autoCost
|
|
207
|
+
if (!firstTime || it.time < firstTime) firstTime = it.time
|
|
208
|
+
if (it.time > lastTime) lastTime = it.time
|
|
209
|
+
}
|
|
210
|
+
const denom = agg.cacheRead + agg.input
|
|
211
|
+
agg.hitRate = denom > 0 ? (agg.cacheRead / denom * 100) : 0
|
|
212
|
+
agg.time = { start: firstTime, end: lastTime }
|
|
213
|
+
return agg
|
|
214
|
+
}
|
|
215
|
+
|
|
164
216
|
const msg = (e) => String((e && e.message) || e)
|
|
165
217
|
const fail = (message) => ({ ok: false, error: message })
|
|
166
218
|
const pad2 = (n) => (n < 10 ? '0' : '') + n
|
|
@@ -203,6 +255,7 @@ export default {
|
|
|
203
255
|
function buildDays() {
|
|
204
256
|
const map = {}
|
|
205
257
|
for (const r of records) {
|
|
258
|
+
if (!isRealCall(r)) continue;
|
|
206
259
|
const key = bjKey(r.time)
|
|
207
260
|
let d = map[key]
|
|
208
261
|
if (!d) {
|
|
@@ -341,12 +394,14 @@ export default {
|
|
|
341
394
|
model: String(raw.model || ''),
|
|
342
395
|
provider: String(raw.provider || ''),
|
|
343
396
|
purpose: String(raw.purpose || ''),
|
|
397
|
+
sessionId: String(raw.sessionId || ''),
|
|
344
398
|
inputTokens: toNum(raw.inputTokens),
|
|
345
399
|
outputTokens: toNum(raw.outputTokens),
|
|
346
400
|
cacheReadTokens: toNum(raw.cacheReadTokens),
|
|
347
401
|
cacheWriteTokens: toNum(raw.cacheWriteTokens),
|
|
348
402
|
reasoningTokens: toNum(raw.reasoningTokens),
|
|
349
403
|
finishReason: String(raw.finishReason || ''),
|
|
404
|
+
interrupted: !!raw.interrupted,
|
|
350
405
|
usdCnyRate: toNum(raw.usdCnyRate),
|
|
351
406
|
fxDate: String(raw.fxDate || '')
|
|
352
407
|
}
|
|
@@ -489,6 +544,7 @@ export default {
|
|
|
489
544
|
const model = (options && options.model) || ''
|
|
490
545
|
const provider = (options && options.provider) || ''
|
|
491
546
|
const purpose = options && options.purpose ? String(options.purpose) : ''
|
|
547
|
+
let sessionId = options && options.sessionId ? String(options.sessionId) : ''
|
|
492
548
|
const startedAt = Date.now()
|
|
493
549
|
let usage = null
|
|
494
550
|
let finishReason = ''
|
|
@@ -505,10 +561,14 @@ export default {
|
|
|
505
561
|
yield chunk
|
|
506
562
|
}
|
|
507
563
|
} finally {
|
|
564
|
+
if (!sessionId) {
|
|
565
|
+
try { const ag = currentAgent(); if (ag && ag.session && ag.session.id) sessionId = String(ag.session.id) } catch (e) {}
|
|
566
|
+
}
|
|
567
|
+
if (provider === 'digital-ocean' || provider === 'digitalocean') {
|
|
568
|
+
try { await refreshFxRate(false) } catch (e) {}
|
|
569
|
+
}
|
|
570
|
+
const isDO = provider === 'digital-ocean' || provider === 'digitalocean'
|
|
508
571
|
if (usage) {
|
|
509
|
-
if (provider === 'digital-ocean' || provider === 'digitalocean') {
|
|
510
|
-
try { await refreshFxRate(false) } catch (e) {}
|
|
511
|
-
}
|
|
512
572
|
// 兼容性:DeepSeek 系 provider 的 usage 不单独上报 cacheWriteTokens
|
|
513
573
|
// (缓存写入发生在未命中时,即 cacheWriteTokens == inputTokens)。
|
|
514
574
|
// 当上游未提供该字段时,用未命中 token 数(inputTokens)兜底,避免
|
|
@@ -519,26 +579,49 @@ export default {
|
|
|
519
579
|
model,
|
|
520
580
|
provider,
|
|
521
581
|
purpose,
|
|
582
|
+
sessionId,
|
|
522
583
|
inputTokens: usage.inputTokens || 0,
|
|
523
584
|
outputTokens: usage.outputTokens || 0,
|
|
524
585
|
cacheReadTokens: usage.cacheReadTokens || 0,
|
|
525
586
|
cacheWriteTokens: cacheWrite,
|
|
526
587
|
reasoningTokens: usage.reasoningTokens || 0,
|
|
527
588
|
finishReason,
|
|
528
|
-
usdCnyRate:
|
|
529
|
-
fxDate:
|
|
589
|
+
usdCnyRate: isDO ? (FX.rate || 0) : 0,
|
|
590
|
+
fxDate: isDO ? (FX.date || '') : ''
|
|
591
|
+
})
|
|
592
|
+
} else if (isRealCall({ model, provider, time: startedAt })) {
|
|
593
|
+
// 兜底:harness 在流被中断(aborted / error / timeout)时不会产出
|
|
594
|
+
// usage chunk(usage 只在收到 [DONE] 哨兵后才由 adapter yield),
|
|
595
|
+
// 但官方后台仍会按该次请求的实际 token 计费。这里补记一条 0-token
|
|
596
|
+
// 的「中断调用」,使调用次数与官方口径对齐;token 与费用均为 0,
|
|
597
|
+
// 不会虚增消耗。interrupted 标记供客户端 UI 区分展示。
|
|
598
|
+
records.push({
|
|
599
|
+
time: startedAt,
|
|
600
|
+
model,
|
|
601
|
+
provider,
|
|
602
|
+
purpose,
|
|
603
|
+
sessionId,
|
|
604
|
+
inputTokens: 0,
|
|
605
|
+
outputTokens: 0,
|
|
606
|
+
cacheReadTokens: 0,
|
|
607
|
+
cacheWriteTokens: 0,
|
|
608
|
+
reasoningTokens: 0,
|
|
609
|
+
finishReason: finishReason || 'aborted',
|
|
610
|
+
interrupted: true,
|
|
611
|
+
usdCnyRate: 0,
|
|
612
|
+
fxDate: ''
|
|
530
613
|
})
|
|
531
|
-
if (records.length > MAX_RECORDS) records.splice(0, records.length - MAX_RECORDS)
|
|
532
|
-
try {
|
|
533
|
-
const agent = currentAgent()
|
|
534
|
-
const sp = ctx.get('sandboxPolicy')
|
|
535
|
-
if (sp && typeof sp.resolve === 'function' && agent && agent.session) {
|
|
536
|
-
const policy = sp.resolve({ session: agent.session })
|
|
537
|
-
if (policy && policy.workspaceRoot) cachedPolicy = policy
|
|
538
|
-
}
|
|
539
|
-
} catch (e) {}
|
|
540
|
-
ensureSessionRoot().then(persistNow).catch(() => {})
|
|
541
614
|
}
|
|
615
|
+
if (records.length > MAX_RECORDS) records.splice(0, records.length - MAX_RECORDS)
|
|
616
|
+
try {
|
|
617
|
+
const agent = currentAgent()
|
|
618
|
+
const sp = ctx.get('sandboxPolicy')
|
|
619
|
+
if (sp && typeof sp.resolve === 'function' && agent && agent.session) {
|
|
620
|
+
const policy = sp.resolve({ session: agent.session })
|
|
621
|
+
if (policy && policy.workspaceRoot) cachedPolicy = policy
|
|
622
|
+
}
|
|
623
|
+
} catch (e) {}
|
|
624
|
+
ensureSessionRoot().then(persistNow).catch(() => {})
|
|
542
625
|
}
|
|
543
626
|
}
|
|
544
627
|
|
|
@@ -1129,17 +1212,23 @@ export default {
|
|
|
1129
1212
|
switch (action) {
|
|
1130
1213
|
case 'list': {
|
|
1131
1214
|
try { await refreshFxRate(false) } catch (e) {}
|
|
1132
|
-
const items = records.map(
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1215
|
+
const items = records.filter(isRealCall).map(projectRecord)
|
|
1216
|
+
const toolItems = records.filter((r) => !isRealCall(r)).map(projectRecord)
|
|
1217
|
+
return { ok: true, records: items, count: items.length, toolCalls: toolItems, dataPath, persistOk, persistError, pricing: PRICING, effectiveAt: EFFECTIVE_AT, days: buildDays(), fx: FX }
|
|
1218
|
+
}
|
|
1219
|
+
case 'tokenForMessage': {
|
|
1220
|
+
// 消息底部弹窗:分两层统计——整场对话累计(conversation)+ 本轮明细(aggregate/records)。
|
|
1221
|
+
const sid = body && body.sessionId ? String(body.sessionId) : ''
|
|
1222
|
+
const from = Number(body && body.from) || 0
|
|
1223
|
+
const to = Number(body && body.to) || 0
|
|
1224
|
+
let sessionRecs = records.filter(isRealCall)
|
|
1225
|
+
if (sid) sessionRecs = sessionRecs.filter((r) => String(r.sessionId || '') === sid)
|
|
1226
|
+
let turnRecs = sessionRecs
|
|
1227
|
+
if (from > 0) turnRecs = turnRecs.filter((r) => r.time >= from)
|
|
1228
|
+
if (to > 0) turnRecs = turnRecs.filter((r) => r.time <= to)
|
|
1229
|
+
const convoAgg = computeAgg(sessionRecs.map(projectRecord))
|
|
1230
|
+
const turnAgg = computeAgg(turnRecs.map(projectRecord))
|
|
1231
|
+
return { ok: true, records: turnRecs.map(projectRecord), aggregate: turnAgg, conversation: convoAgg, count: turnRecs.length, from, to }
|
|
1143
1232
|
}
|
|
1144
1233
|
case 'clear': {
|
|
1145
1234
|
const n = records.length
|
package/package.json
CHANGED
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@feiyang666/dsh-usage-plugin",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "DeepSeek Harness usage & cost tracker plugin: per-call token/cache-hit stats, peak/off-peak billing, DeepSeek balance query, CSV/JSON/PNG export with custom destination, and persistent local storage. Ships a host half plus a web client half in one npm package; installs into a DSH profile as a dsh.bundle with one command (dsh plugin --profile web add @feiyang666/dsh-usage-plugin).",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"deepseek",
|
|
7
|
-
"harness",
|
|
8
|
-
"dsh",
|
|
9
|
-
"plugin",
|
|
10
|
-
"usage",
|
|
11
|
-
"cost",
|
|
12
|
-
"tokens",
|
|
13
|
-
"cache",
|
|
14
|
-
"balance"
|
|
15
|
-
],
|
|
16
|
-
"license": "MIT",
|
|
17
|
-
"type": "module",
|
|
18
|
-
"main": "lib/index.js",
|
|
19
|
-
"repository": {
|
|
20
|
-
"type": "git",
|
|
21
|
-
"url": "git+https://github.com/feiyang-dev/dsh-usage-plugin.git"
|
|
22
|
-
},
|
|
23
|
-
"contributors": [
|
|
24
|
-
{
|
|
25
|
-
"name": "ayleen",
|
|
26
|
-
"url": "https://github.com/ayleen"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"name": "wuhuqif176",
|
|
30
|
-
"url": "https://github.com/wuhuqif176"
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"name": "Martin-soaring-dev",
|
|
34
|
-
"url": "https://github.com/Martin-soaring-dev"
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"name": "liu3734",
|
|
38
|
-
"url": "https://github.com/liu3734"
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"name": "mumuer1024",
|
|
42
|
-
"url": "https://github.com/mumuer1024"
|
|
43
|
-
}
|
|
44
|
-
],
|
|
45
|
-
"homepage": "https://github.com/feiyang-dev/dsh-usage-plugin#readme",
|
|
46
|
-
"bugs": {
|
|
47
|
-
"url": "https://github.com/feiyang-dev/dsh-usage-plugin/issues"
|
|
48
|
-
},
|
|
49
|
-
"exports": {
|
|
50
|
-
".": "./lib/index.js",
|
|
51
|
-
"./client": "./lib/client.js",
|
|
52
|
-
"./package.json": "./package.json"
|
|
53
|
-
},
|
|
54
|
-
"engines": {
|
|
55
|
-
"node": ">=18"
|
|
56
|
-
},
|
|
57
|
-
"dsh": {
|
|
58
|
-
"bundle": {
|
|
59
|
-
"patch": "./cordis.patch.yml"
|
|
60
|
-
},
|
|
61
|
-
"client": {
|
|
62
|
-
"platform": "web",
|
|
63
|
-
"inject": [
|
|
64
|
-
"@deepseek-ai/dsh-client-ui-conversation"
|
|
65
|
-
]
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
"files": [
|
|
69
|
-
"lib",
|
|
70
|
-
"scripts",
|
|
71
|
-
"cordis.patch.yml",
|
|
72
|
-
"README.md",
|
|
73
|
-
"README.zh.md",
|
|
74
|
-
"CHANGELOG.md"
|
|
75
|
-
],
|
|
76
|
-
"scripts": {
|
|
77
|
-
"wire": "node scripts/wire.js",
|
|
78
|
-
"check": "node scripts/check-package.js",
|
|
79
|
-
"prepublishOnly": "node scripts/check-package.js",
|
|
80
|
-
"pack": "npm pack"
|
|
81
|
-
},
|
|
82
|
-
"peerDependencies": {
|
|
83
|
-
"@deepseek-ai/cordis": "^4.0.1"
|
|
84
|
-
},
|
|
85
|
-
"dependencies": {
|
|
86
|
-
"undici": "^7.0.0"
|
|
87
|
-
}
|
|
88
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@feiyang666/dsh-usage-plugin",
|
|
3
|
+
"version": "1.14.1",
|
|
4
|
+
"description": "DeepSeek Harness usage & cost tracker plugin: per-call token/cache-hit stats, peak/off-peak billing, DeepSeek balance query, CSV/JSON/PNG export with custom destination, and persistent local storage. Ships a host half plus a web client half in one npm package; installs into a DSH profile as a dsh.bundle with one command (dsh plugin --profile web add @feiyang666/dsh-usage-plugin).",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"deepseek",
|
|
7
|
+
"harness",
|
|
8
|
+
"dsh",
|
|
9
|
+
"plugin",
|
|
10
|
+
"usage",
|
|
11
|
+
"cost",
|
|
12
|
+
"tokens",
|
|
13
|
+
"cache",
|
|
14
|
+
"balance"
|
|
15
|
+
],
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"type": "module",
|
|
18
|
+
"main": "lib/index.js",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/feiyang-dev/dsh-usage-plugin.git"
|
|
22
|
+
},
|
|
23
|
+
"contributors": [
|
|
24
|
+
{
|
|
25
|
+
"name": "ayleen",
|
|
26
|
+
"url": "https://github.com/ayleen"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "wuhuqif176",
|
|
30
|
+
"url": "https://github.com/wuhuqif176"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "Martin-soaring-dev",
|
|
34
|
+
"url": "https://github.com/Martin-soaring-dev"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "liu3734",
|
|
38
|
+
"url": "https://github.com/liu3734"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "mumuer1024",
|
|
42
|
+
"url": "https://github.com/mumuer1024"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"homepage": "https://github.com/feiyang-dev/dsh-usage-plugin#readme",
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/feiyang-dev/dsh-usage-plugin/issues"
|
|
48
|
+
},
|
|
49
|
+
"exports": {
|
|
50
|
+
".": "./lib/index.js",
|
|
51
|
+
"./client": "./lib/client.js",
|
|
52
|
+
"./package.json": "./package.json"
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=18"
|
|
56
|
+
},
|
|
57
|
+
"dsh": {
|
|
58
|
+
"bundle": {
|
|
59
|
+
"patch": "./cordis.patch.yml"
|
|
60
|
+
},
|
|
61
|
+
"client": {
|
|
62
|
+
"platform": "web",
|
|
63
|
+
"inject": [
|
|
64
|
+
"@deepseek-ai/dsh-client-ui-conversation"
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"files": [
|
|
69
|
+
"lib",
|
|
70
|
+
"scripts",
|
|
71
|
+
"cordis.patch.yml",
|
|
72
|
+
"README.md",
|
|
73
|
+
"README.zh.md",
|
|
74
|
+
"CHANGELOG.md"
|
|
75
|
+
],
|
|
76
|
+
"scripts": {
|
|
77
|
+
"wire": "node scripts/wire.js",
|
|
78
|
+
"check": "node scripts/check-package.js",
|
|
79
|
+
"prepublishOnly": "node scripts/check-package.js",
|
|
80
|
+
"pack": "npm pack"
|
|
81
|
+
},
|
|
82
|
+
"peerDependencies": {
|
|
83
|
+
"@deepseek-ai/cordis": "^4.0.1"
|
|
84
|
+
},
|
|
85
|
+
"dependencies": {
|
|
86
|
+
"undici": "^7.0.0"
|
|
87
|
+
}
|
|
88
|
+
}
|