dsh-deepseek-peak-clock 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/README.md +78 -2
- package/client.js +278 -0
- package/cordis.patch.yml +3 -0
- package/icon.svg +6 -0
- package/index.js +7 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +49 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 esketids
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,79 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-deepseek-peak-clock
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A [DeepSeek Harness](https://github.com/deepseek-ai) plugin that shows whether the DeepSeek API is
|
|
4
|
+
in its **peak** or **off-peak** billing window — right in the composer HUD row, next to turns,
|
|
5
|
+
tok/s and cache hit rate.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
● Off-peak · ends in 1h 22m green dot, half price
|
|
9
|
+
● Peak · ends in 2h 04m amber dot, full price
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The countdown ticks every second. Hovering the cell shows the window end in your local time and the
|
|
13
|
+
current per-1M-token rates:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
Peak · input / cached input / output · until 12:00
|
|
17
|
+
Flash $0.30 / $0.006 / $1.20 · Pro $1.32 / $0.044 / $3.96 · per 1M tokens
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Schedule
|
|
21
|
+
|
|
22
|
+
Peak windows are **01:00–04:00** and **06:00–10:00 UTC**, everything else is off-peak at half price.
|
|
23
|
+
Since 2026-08-22 16:00 UTC the split only applies Monday–Friday Beijing time; Saturdays, Sundays and
|
|
24
|
+
Chinese public holidays are off-peak all day.
|
|
25
|
+
|
|
26
|
+
The rules are a port of the logic behind [deepakness.com/deepseek](https://deepakness.com/deepseek/)
|
|
27
|
+
and its [price clock extension](https://github.com/deepakness/deepseek-price-clock), which in turn
|
|
28
|
+
follow the [official DeepSeek pricing page](https://api-docs.deepseek.com/quick_start/pricing).
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
This is a Harness bundle: a package whose `cordis.patch.yml` inserts one Loader row.
|
|
33
|
+
|
|
34
|
+
1. Clone the repo somewhere stable (the profile links to the directory, so do not delete it).
|
|
35
|
+
2. Install it into your profile with the plugin manager, pointing at the checkout directory:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
plugin_manager install_bundle /absolute/path/to/dsh-deepseek-peak-clock
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or add it by hand to your profile's Cordis composition:
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
- insert:
|
|
45
|
+
- id: deepseek-peak-clock
|
|
46
|
+
name: dsh-deepseek-peak-clock
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
3. Refresh the Web GUI. The cell appears under the composer; it is session-scoped, so open a
|
|
50
|
+
session to see it.
|
|
51
|
+
|
|
52
|
+
The Host half is a no-op: the schedule is pure UTC arithmetic, so the clock renders entirely in the
|
|
53
|
+
browser and works offline.
|
|
54
|
+
|
|
55
|
+
## Configuration
|
|
56
|
+
|
|
57
|
+
None. The plugin adds one locale namespace, one HUD cell and nothing else.
|
|
58
|
+
|
|
59
|
+
## Maintenance
|
|
60
|
+
|
|
61
|
+
`CN_HOLIDAYS` in `client.js` lists Chinese public holidays that DeepSeek bills off-peak all day.
|
|
62
|
+
The State Council publishes the next year's arrangement around November, so add those dates when
|
|
63
|
+
they are announced. Everything else (windows, weekend rule) only changes when DeepSeek changes its
|
|
64
|
+
pricing, which this plugin does not detect automatically — compare with the pricing page
|
|
65
|
+
occasionally.
|
|
66
|
+
|
|
67
|
+
## Layout
|
|
68
|
+
|
|
69
|
+
| File | Purpose |
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| `index.js` | Host half (empty `apply`; no services, no network) |
|
|
72
|
+
| `client.js` | Schedule port + the HUD cell component |
|
|
73
|
+
| `cordis.patch.yml` | Loader row that activates the bundle |
|
|
74
|
+
| `locale/en.json`, `locale/zh.json` | Plugin title and description for the Plugins page |
|
|
75
|
+
| `icon.svg` | Half-green/half-red clock icon |
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT. The schedule logic derives from DeepakNess's price clock; see the license file.
|
package/client.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DeepSeek peak/off-peak clock, rendered in the HUD row under the composer.
|
|
3
|
+
*
|
|
4
|
+
* Schedule logic is a port of deepakness.com/deepseek and
|
|
5
|
+
* github.com/deepakness/deepseek-price-clock `price.js` — keep SWITCH_MINUTES,
|
|
6
|
+
* WEEKEND_RULE_START and CN_HOLIDAYS in sync with the site.
|
|
7
|
+
*/
|
|
8
|
+
window.__ModuleLoader__.load({
|
|
9
|
+
id: 'dsh-deepseek-peak-clock',
|
|
10
|
+
factory(require) {
|
|
11
|
+
const React = require('react');
|
|
12
|
+
const h = React.createElement;
|
|
13
|
+
|
|
14
|
+
const NS = 'deepseek-peak-clock';
|
|
15
|
+
const SLOT = 'conversation.composer.dock';
|
|
16
|
+
const CELL_ID = 'deepseek-peak-clock';
|
|
17
|
+
|
|
18
|
+
// --- schedule ---------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
// Peak window switch instants in UTC minutes-of-day: 01:00 and 06:00 open
|
|
21
|
+
// a peak window, 04:00 and 10:00 close one. Everything else is off-peak.
|
|
22
|
+
const SWITCH_MINUTES = [60, 240, 360, 600];
|
|
23
|
+
|
|
24
|
+
// Since 00:00 Beijing time on Sunday August 23, 2026 (16:00 UTC Saturday
|
|
25
|
+
// August 22) the split only applies Monday to Friday Beijing time.
|
|
26
|
+
const WEEKEND_RULE_START = Date.UTC(2026, 7, 22, 16);
|
|
27
|
+
|
|
28
|
+
// Chinese public holidays as Beijing dates; DeepSeek bills them off-peak
|
|
29
|
+
// all day. Add the next year's dates once the State Council announces them.
|
|
30
|
+
const CN_HOLIDAYS = [
|
|
31
|
+
['2026-09-25', '2026-09-27'], // Mid-Autumn
|
|
32
|
+
['2026-10-01', '2026-10-07'], // National Day
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
function isBeijingWeekend(date) {
|
|
36
|
+
const day = new Date(date.getTime() + 8 * 3600000).getUTCDay();
|
|
37
|
+
return day === 0 || day === 6;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function beijingDateKey(date) {
|
|
41
|
+
return new Date(date.getTime() + 8 * 3600000).toISOString().slice(0, 10);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function isBeijingHoliday(date) {
|
|
45
|
+
const key = beijingDateKey(date);
|
|
46
|
+
for (const [from, to] of CN_HOLIDAYS) {
|
|
47
|
+
if (key >= from && key <= to) return true;
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// A Saturday, Sunday or public holiday under the current rules is off-peak
|
|
53
|
+
// all day.
|
|
54
|
+
function offPeakAllDay(date) {
|
|
55
|
+
return (
|
|
56
|
+
date.getTime() >= WEEKEND_RULE_START &&
|
|
57
|
+
(isBeijingWeekend(date) || isBeijingHoliday(date))
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function kindAtInstant(date) {
|
|
62
|
+
if (offPeakAllDay(date)) return 'off';
|
|
63
|
+
const minuteOfDay = date.getUTCHours() * 60 + date.getUTCMinutes();
|
|
64
|
+
return (minuteOfDay >= 60 && minuteOfDay < 240) ||
|
|
65
|
+
(minuteOfDay >= 360 && minuteOfDay < 600)
|
|
66
|
+
? 'peak'
|
|
67
|
+
: 'off';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function isSwitchInstant(date) {
|
|
71
|
+
const minuteOfDay = date.getUTCHours() * 60 + date.getUTCMinutes();
|
|
72
|
+
for (const m of SWITCH_MINUTES) {
|
|
73
|
+
if (minuteOfDay === m) return !offPeakAllDay(date);
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function nextSwitch(now) {
|
|
79
|
+
const dayStart = Date.UTC(
|
|
80
|
+
now.getUTCFullYear(),
|
|
81
|
+
now.getUTCMonth(),
|
|
82
|
+
now.getUTCDate(),
|
|
83
|
+
);
|
|
84
|
+
let day = 0;
|
|
85
|
+
let index = 0;
|
|
86
|
+
// Bounded scan: a gated weekend/holiday stretch never exceeds a few days.
|
|
87
|
+
for (let guard = 0; guard < 4000; guard++) {
|
|
88
|
+
const instant =
|
|
89
|
+
dayStart + day * 86400000 + SWITCH_MINUTES[index] * 60000;
|
|
90
|
+
const candidate = new Date(instant);
|
|
91
|
+
if (instant > now.getTime() && isSwitchInstant(candidate)) {
|
|
92
|
+
return { date: candidate, kind: kindAtInstant(candidate) };
|
|
93
|
+
}
|
|
94
|
+
index++;
|
|
95
|
+
if (index >= SWITCH_MINUTES.length) {
|
|
96
|
+
index = 0;
|
|
97
|
+
day++;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// --- formatting -------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
function formatDuration(ms) {
|
|
106
|
+
const total = Math.max(0, Math.round(ms / 1000));
|
|
107
|
+
const hours = Math.floor(total / 3600);
|
|
108
|
+
const minutes = Math.floor((total % 3600) / 60);
|
|
109
|
+
const seconds = total % 60;
|
|
110
|
+
if (hours > 0) {
|
|
111
|
+
return hours + 'h ' + String(minutes).padStart(2, '0') + 'm';
|
|
112
|
+
}
|
|
113
|
+
if (minutes > 0) {
|
|
114
|
+
return minutes + 'm ' + String(seconds).padStart(2, '0') + 's';
|
|
115
|
+
}
|
|
116
|
+
return seconds + 's';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function formatLocalTime(date) {
|
|
120
|
+
try {
|
|
121
|
+
return date.toLocaleTimeString([], {
|
|
122
|
+
hour: '2-digit',
|
|
123
|
+
minute: '2-digit',
|
|
124
|
+
});
|
|
125
|
+
} catch {
|
|
126
|
+
return date.getUTCHours() + ':00';
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Rates per 1M tokens, from deepakness.com/deepseek (off-peak is half price).
|
|
131
|
+
const RATES = {
|
|
132
|
+
off: {
|
|
133
|
+
flash: ['$0.15', '$0.003', '$0.60'],
|
|
134
|
+
pro: ['$0.66', '$0.022', '$1.98'],
|
|
135
|
+
},
|
|
136
|
+
peak: {
|
|
137
|
+
flash: ['$0.30', '$0.006', '$1.20'],
|
|
138
|
+
pro: ['$1.32', '$0.044', '$3.96'],
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
function rateLine(kind, t) {
|
|
143
|
+
const table = RATES[kind];
|
|
144
|
+
return (
|
|
145
|
+
'Flash ' +
|
|
146
|
+
table.flash.join(' / ') +
|
|
147
|
+
' · Pro ' +
|
|
148
|
+
table.pro.join(' / ') +
|
|
149
|
+
' · ' +
|
|
150
|
+
t('perMillion')
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// --- dictionaries -----------------------------------------------------
|
|
155
|
+
|
|
156
|
+
const DICTS = {
|
|
157
|
+
en: {
|
|
158
|
+
offPeak: 'Off-peak',
|
|
159
|
+
peak: 'Peak',
|
|
160
|
+
endsIn: 'ends in',
|
|
161
|
+
endsAt: 'next window',
|
|
162
|
+
until: 'until',
|
|
163
|
+
prices: 'input / cached input / output',
|
|
164
|
+
perMillion: 'per 1M tokens',
|
|
165
|
+
aria: 'DeepSeek API price window',
|
|
166
|
+
},
|
|
167
|
+
zh: {
|
|
168
|
+
offPeak: '低谷',
|
|
169
|
+
peak: '高峰',
|
|
170
|
+
endsIn: '剩余',
|
|
171
|
+
endsAt: '下次切换',
|
|
172
|
+
until: '截至',
|
|
173
|
+
prices: '输入 / 缓存输入 / 输出',
|
|
174
|
+
perMillion: '每百万 tokens',
|
|
175
|
+
aria: 'DeepSeek API 峰谷计费时段',
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// --- component --------------------------------------------------------
|
|
180
|
+
|
|
181
|
+
function useTicker(periodMs) {
|
|
182
|
+
const [now, setNow] = React.useState(() => new Date());
|
|
183
|
+
React.useEffect(() => {
|
|
184
|
+
const id = setInterval(() => setNow(new Date()), periodMs);
|
|
185
|
+
return () => clearInterval(id);
|
|
186
|
+
}, [periodMs]);
|
|
187
|
+
return now;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function Clock(props) {
|
|
191
|
+
const t = props.t;
|
|
192
|
+
const now = useTicker(1000);
|
|
193
|
+
const next = nextSwitch(now);
|
|
194
|
+
const kind = kindAtInstant(now);
|
|
195
|
+
const offPeak = kind === 'off';
|
|
196
|
+
|
|
197
|
+
if (!next) return null;
|
|
198
|
+
|
|
199
|
+
const label = t(offPeak ? 'offPeak' : 'peak');
|
|
200
|
+
const remaining = formatDuration(next.date.getTime() - now.getTime());
|
|
201
|
+
const flip = formatLocalTime(next.date);
|
|
202
|
+
const accent = offPeak
|
|
203
|
+
? 'var(--dsw-alias-state-success-primary)'
|
|
204
|
+
: 'var(--dsw-alias-state-warn-primary)';
|
|
205
|
+
|
|
206
|
+
const title =
|
|
207
|
+
label +
|
|
208
|
+
' · ' +
|
|
209
|
+
t('prices') +
|
|
210
|
+
' · ' +
|
|
211
|
+
t('until') +
|
|
212
|
+
' ' +
|
|
213
|
+
flip +
|
|
214
|
+
'\n' +
|
|
215
|
+
rateLine(kind, t);
|
|
216
|
+
|
|
217
|
+
return h(
|
|
218
|
+
'span',
|
|
219
|
+
{
|
|
220
|
+
title,
|
|
221
|
+
'aria-label': t('aria') + ': ' + label + ' ' + remaining,
|
|
222
|
+
style: {
|
|
223
|
+
display: 'inline-flex',
|
|
224
|
+
alignItems: 'center',
|
|
225
|
+
gap: '6px',
|
|
226
|
+
fontSize: '11px',
|
|
227
|
+
lineHeight: 1.4,
|
|
228
|
+
whiteSpace: 'nowrap',
|
|
229
|
+
userSelect: 'none',
|
|
230
|
+
color: 'var(--dsw-alias-label-secondary)',
|
|
231
|
+
fontVariantNumeric: 'tabular-nums',
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
h('span', {
|
|
235
|
+
'aria-hidden': true,
|
|
236
|
+
style: {
|
|
237
|
+
width: '6px',
|
|
238
|
+
height: '6px',
|
|
239
|
+
borderRadius: '50%',
|
|
240
|
+
flex: '0 0 auto',
|
|
241
|
+
background: accent,
|
|
242
|
+
boxShadow: '0 0 0 3px color-mix(in srgb, ' + accent + ' 18%, transparent)',
|
|
243
|
+
},
|
|
244
|
+
}),
|
|
245
|
+
h(
|
|
246
|
+
'span',
|
|
247
|
+
{ style: { color: 'var(--dsw-alias-label-primary)' } },
|
|
248
|
+
label,
|
|
249
|
+
),
|
|
250
|
+
h('span', { 'aria-hidden': true, opacity: 0.5 }, '·'),
|
|
251
|
+
h('span', null, t('endsIn') + ' ' + remaining),
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return {
|
|
256
|
+
inject: ['slots', 'locale'],
|
|
257
|
+
apply(ctx) {
|
|
258
|
+
ctx.effect(() => {
|
|
259
|
+
const disposers = [];
|
|
260
|
+
for (const [locale, dict] of Object.entries(DICTS)) {
|
|
261
|
+
disposers.push(ctx.locale.register(NS, locale, dict));
|
|
262
|
+
}
|
|
263
|
+
return () => {
|
|
264
|
+
for (const dispose of disposers) dispose();
|
|
265
|
+
};
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
const t = ctx.locale.bind(NS);
|
|
269
|
+
|
|
270
|
+
ctx.slots.inject(SLOT, () =>
|
|
271
|
+
ctx.slots.register({ name: SLOT, id: CELL_ID, order: 2 }, () =>
|
|
272
|
+
h(Clock, { t }),
|
|
273
|
+
),
|
|
274
|
+
);
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
},
|
|
278
|
+
});
|
package/cordis.patch.yml
ADDED
package/icon.svg
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
2
|
+
<circle cx="32" cy="32" r="26" fill="#16a34a"/>
|
|
3
|
+
<path d="M32 6 A26 26 0 0 1 32 58 Z" fill="#dc2626"/>
|
|
4
|
+
<circle cx="32" cy="32" r="26" fill="none" stroke="#0f172a" stroke-opacity="0.22" stroke-width="2"/>
|
|
5
|
+
<path d="M32 17 V32 L42 39" fill="none" stroke="#ffffff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
6
|
+
</svg>
|
package/index.js
ADDED
package/locale/en.json
ADDED
package/locale/zh.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,51 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-deepseek-peak-clock",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
6
|
-
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "DeepSeek peak/off-peak price clock for the DeepSeek Harness composer HUD.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "esketids",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"deepseek",
|
|
10
|
+
"deepseek-harness",
|
|
11
|
+
"dsh",
|
|
12
|
+
"dsh-plugin",
|
|
13
|
+
"pricing",
|
|
14
|
+
"hud"
|
|
15
|
+
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/esketids/dsh-deepseek-peak-clock.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/esketids/dsh-deepseek-peak-clock#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/esketids/dsh-deepseek-peak-clock/issues"
|
|
23
|
+
},
|
|
24
|
+
"exports": {
|
|
25
|
+
".": "./index.js",
|
|
26
|
+
"./client": "./client.js",
|
|
27
|
+
"./locale/*.json": "./locale/*.json",
|
|
28
|
+
"./icon": "./icon.svg"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"index.js",
|
|
32
|
+
"client.js",
|
|
33
|
+
"cordis.patch.yml",
|
|
34
|
+
"locale/*.json",
|
|
35
|
+
"icon.svg",
|
|
36
|
+
"README.md",
|
|
37
|
+
"LICENSE"
|
|
38
|
+
],
|
|
39
|
+
"dsh": {
|
|
40
|
+
"bundle": {
|
|
41
|
+
"patch": "./cordis.patch.yml"
|
|
42
|
+
},
|
|
43
|
+
"client": {
|
|
44
|
+
"platform": "web",
|
|
45
|
+
"immediately": true,
|
|
46
|
+
"inject": [
|
|
47
|
+
"@deepseek-ai/dsh-client-ui-conversation"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|