dsh-plugin-token-heatmap 0.1.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/LICENSE +21 -0
- package/README.md +95 -0
- package/cordis.patch.yml +4 -0
- package/lib/client.js +900 -0
- package/lib/index.js +335 -0
- package/package.json +85 -0
package/lib/index.js
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __knownSymbol = (name2, symbol) => (symbol = Symbol[name2]) ? symbol : Symbol.for("Symbol." + name2);
|
|
5
|
+
var __typeError = (msg) => {
|
|
6
|
+
throw TypeError(msg);
|
|
7
|
+
};
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
10
|
+
var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
|
|
11
|
+
var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
|
|
12
|
+
var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
|
|
13
|
+
var __decoratorContext = (kind, name2, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name: name2, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
|
|
14
|
+
var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
|
|
15
|
+
var __runInitializers = (array, flags, self, value) => {
|
|
16
|
+
for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
|
|
17
|
+
return value;
|
|
18
|
+
};
|
|
19
|
+
var __decorateElement = (array, flags, name2, decorators, target, extra) => {
|
|
20
|
+
var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
|
|
21
|
+
var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
|
|
22
|
+
var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
|
|
23
|
+
var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name2]() {
|
|
24
|
+
return __privateGet(this, extra);
|
|
25
|
+
}, set [name2](x) {
|
|
26
|
+
return __privateSet(this, extra, x);
|
|
27
|
+
} }, name2));
|
|
28
|
+
k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name2) : __name(target, name2);
|
|
29
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
30
|
+
ctx = __decoratorContext(k, name2, done = {}, array[3], extraInitializers);
|
|
31
|
+
if (k) {
|
|
32
|
+
ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name2 in x };
|
|
33
|
+
if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name2];
|
|
34
|
+
if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name2] = y;
|
|
35
|
+
}
|
|
36
|
+
it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
|
|
37
|
+
if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
|
|
38
|
+
else if (typeof it !== "object" || it === null) __typeError("Object expected");
|
|
39
|
+
else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
|
|
40
|
+
}
|
|
41
|
+
return k || __decoratorMetadata(array, target), desc && __defProp(target, name2, desc), p ? k ^ 4 ? extra : desc : target;
|
|
42
|
+
};
|
|
43
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
44
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
45
|
+
var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
|
|
46
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
47
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
48
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
49
|
+
|
|
50
|
+
// src/index.ts
|
|
51
|
+
import { dshHomePath } from "@deepseek-ai/dsh-home-paths";
|
|
52
|
+
|
|
53
|
+
// src/day.ts
|
|
54
|
+
function dayKeyOf(time) {
|
|
55
|
+
const d = new Date(time);
|
|
56
|
+
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
57
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
58
|
+
return d.getFullYear() + "-" + m + "-" + day;
|
|
59
|
+
}
|
|
60
|
+
function cutoffKey(now) {
|
|
61
|
+
const d = new Date(now);
|
|
62
|
+
return dayKeyOf(new Date(d.getFullYear(), d.getMonth() - 12, 1).getTime());
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/backfill.ts
|
|
66
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
67
|
+
import { join } from "node:path";
|
|
68
|
+
|
|
69
|
+
// src/usage.ts
|
|
70
|
+
function emptyTotals() {
|
|
71
|
+
return { total: 0, input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
72
|
+
}
|
|
73
|
+
function addUsage(map, day, input, output, cacheRead = 0, cacheWrite = 0) {
|
|
74
|
+
const entry = map[day] ?? (map[day] = emptyTotals());
|
|
75
|
+
entry.input += input;
|
|
76
|
+
entry.output += output;
|
|
77
|
+
entry.cacheRead += cacheRead;
|
|
78
|
+
entry.cacheWrite += cacheWrite;
|
|
79
|
+
entry.total = entry.input + entry.output + entry.cacheRead + entry.cacheWrite;
|
|
80
|
+
}
|
|
81
|
+
function mergeMaps(target, source) {
|
|
82
|
+
for (const [day, t] of Object.entries(source)) {
|
|
83
|
+
addUsage(target, day, t.input, t.output, t.cacheRead, t.cacheWrite);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function prune(map, cutoff) {
|
|
87
|
+
for (const key of Object.keys(map)) {
|
|
88
|
+
if (key < cutoff) delete map[key];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// src/backfill.ts
|
|
93
|
+
function extractSamples(events) {
|
|
94
|
+
const samples = [];
|
|
95
|
+
for (const event of events) {
|
|
96
|
+
if (event.type !== "assistant/message") continue;
|
|
97
|
+
const usage = event.data.usage;
|
|
98
|
+
if (usage === void 0) continue;
|
|
99
|
+
samples.push({
|
|
100
|
+
day: dayKeyOf(event.time),
|
|
101
|
+
input: usage.inputTokens,
|
|
102
|
+
output: usage.outputTokens,
|
|
103
|
+
cacheRead: usage.cacheReadTokens ?? 0,
|
|
104
|
+
cacheWrite: usage.cacheWriteTokens ?? 0
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return samples;
|
|
108
|
+
}
|
|
109
|
+
function aggregateSamples(global, bySession, sessionId, samples) {
|
|
110
|
+
const map = bySession[sessionId] ?? (bySession[sessionId] = {});
|
|
111
|
+
for (const sample of samples) {
|
|
112
|
+
addUsage(map, sample.day, sample.input, sample.output, sample.cacheRead, sample.cacheWrite);
|
|
113
|
+
addUsage(global, sample.day, sample.input, sample.output, sample.cacheRead, sample.cacheWrite);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
var BackfillRunner = class {
|
|
117
|
+
dir;
|
|
118
|
+
persistence;
|
|
119
|
+
constructor(dir, persistence) {
|
|
120
|
+
this.dir = dir;
|
|
121
|
+
this.persistence = persistence;
|
|
122
|
+
}
|
|
123
|
+
meta() {
|
|
124
|
+
try {
|
|
125
|
+
return JSON.parse(readFileSync(join(this.dir, "meta.json"), "utf8"));
|
|
126
|
+
} catch {
|
|
127
|
+
return { done: false, scanned: 0, skipped: 0, startedAt: null, finishedAt: null };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async run() {
|
|
131
|
+
const prior = this.meta();
|
|
132
|
+
if (prior.done) {
|
|
133
|
+
return { global: {}, bySession: {}, scannedIds: [], scanned: prior.scanned, skipped: prior.skipped, enumerated: false };
|
|
134
|
+
}
|
|
135
|
+
if (this.persistence === void 0) {
|
|
136
|
+
this.writeMeta({ done: true, scanned: 0, skipped: 0, startedAt: Date.now(), finishedAt: Date.now() });
|
|
137
|
+
return { global: {}, bySession: {}, scannedIds: [], scanned: 0, skipped: 0, enumerated: false };
|
|
138
|
+
}
|
|
139
|
+
this.writeMeta({ done: false, scanned: 0, skipped: 0, startedAt: Date.now(), finishedAt: null });
|
|
140
|
+
const headers = await this.persistence.list();
|
|
141
|
+
const global = {};
|
|
142
|
+
const bySession = {};
|
|
143
|
+
const scannedIds = [];
|
|
144
|
+
let skipped = 0;
|
|
145
|
+
for (const header of headers) {
|
|
146
|
+
scannedIds.push(header.id);
|
|
147
|
+
try {
|
|
148
|
+
const { events } = await this.persistence.inspect(header.id);
|
|
149
|
+
aggregateSamples(global, bySession, header.id, extractSamples(events));
|
|
150
|
+
} catch (error) {
|
|
151
|
+
skipped += 1;
|
|
152
|
+
console.error(`[token-heatmap] backfill skipped session ${header.id}:`, error);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const cutoff = cutoffKey(Date.now());
|
|
156
|
+
prune(global, cutoff);
|
|
157
|
+
for (const map of Object.values(bySession)) prune(map, cutoff);
|
|
158
|
+
this.writeMeta({ done: true, scanned: headers.length, skipped, startedAt: prior.startedAt ?? Date.now(), finishedAt: Date.now() });
|
|
159
|
+
return { global, bySession, scannedIds, scanned: headers.length, skipped, enumerated: true };
|
|
160
|
+
}
|
|
161
|
+
writeMeta(meta) {
|
|
162
|
+
try {
|
|
163
|
+
mkdirSync(this.dir, { recursive: true });
|
|
164
|
+
writeFileSync(join(this.dir, "meta.json"), JSON.stringify(meta), "utf8");
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.error("[token-heatmap] meta write failed:", error);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// src/service.ts
|
|
172
|
+
import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
173
|
+
var _getBackfillStatus_dec, _getSessionUsage_dec, _getGlobalUsage_dec, _a, _init;
|
|
174
|
+
var TokenHeatmapService = class extends (_a = TypertRemoteService, _getGlobalUsage_dec = [Remote], _getSessionUsage_dec = [Remote], _getBackfillStatus_dec = [Remote], _a) {
|
|
175
|
+
constructor(ctx, store, backfillMeta) {
|
|
176
|
+
super(ctx, "tokenHeatmap");
|
|
177
|
+
__runInitializers(_init, 5, this);
|
|
178
|
+
__publicField(this, "store");
|
|
179
|
+
__publicField(this, "backfillMeta");
|
|
180
|
+
this.store = store;
|
|
181
|
+
this.backfillMeta = backfillMeta;
|
|
182
|
+
}
|
|
183
|
+
async getGlobalUsage() {
|
|
184
|
+
return { version: this.store.getVersion(), days: this.store.snapshotGlobal() };
|
|
185
|
+
}
|
|
186
|
+
async getSessionUsage(sessionId) {
|
|
187
|
+
return { version: this.store.getVersion(), days: this.store.snapshotSession(sessionId) };
|
|
188
|
+
}
|
|
189
|
+
async getBackfillStatus() {
|
|
190
|
+
return this.backfillMeta();
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
_init = __decoratorStart(_a);
|
|
194
|
+
__decorateElement(_init, 1, "getGlobalUsage", _getGlobalUsage_dec, TokenHeatmapService);
|
|
195
|
+
__decorateElement(_init, 1, "getSessionUsage", _getSessionUsage_dec, TokenHeatmapService);
|
|
196
|
+
__decorateElement(_init, 1, "getBackfillStatus", _getBackfillStatus_dec, TokenHeatmapService);
|
|
197
|
+
__decoratorMetadata(_init, TokenHeatmapService);
|
|
198
|
+
|
|
199
|
+
// src/usage-store.ts
|
|
200
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
201
|
+
import { join as join2 } from "node:path";
|
|
202
|
+
var WRITE_DELAY_MS = 5e3;
|
|
203
|
+
var UsageStore = class {
|
|
204
|
+
dir;
|
|
205
|
+
global = {};
|
|
206
|
+
bySession = {};
|
|
207
|
+
dirty = false;
|
|
208
|
+
timer = null;
|
|
209
|
+
version = 0;
|
|
210
|
+
constructor(dir) {
|
|
211
|
+
this.dir = dir;
|
|
212
|
+
}
|
|
213
|
+
getVersion() {
|
|
214
|
+
return this.version;
|
|
215
|
+
}
|
|
216
|
+
load() {
|
|
217
|
+
const read = (name2) => {
|
|
218
|
+
try {
|
|
219
|
+
return JSON.parse(readFileSync2(join2(this.dir, name2), "utf8"));
|
|
220
|
+
} catch (error) {
|
|
221
|
+
console.error(`[token-heatmap] failed to load ${name2}, starting empty:`, error);
|
|
222
|
+
return void 0;
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
this.global = read("global.json")?.days ?? {};
|
|
226
|
+
this.bySession = read("sessions.json")?.bySession ?? {};
|
|
227
|
+
this.pruneAll();
|
|
228
|
+
}
|
|
229
|
+
addUsage(sessionId, day, input, output, cacheRead = 0, cacheWrite = 0) {
|
|
230
|
+
addUsage(this.global, day, input, output, cacheRead, cacheWrite);
|
|
231
|
+
if (sessionId !== null) {
|
|
232
|
+
const map = this.bySession[sessionId] ?? (this.bySession[sessionId] = {});
|
|
233
|
+
addUsage(map, day, input, output, cacheRead, cacheWrite);
|
|
234
|
+
}
|
|
235
|
+
this.version += 1;
|
|
236
|
+
this.scheduleWrite();
|
|
237
|
+
}
|
|
238
|
+
mergeBackfill(global, bySession) {
|
|
239
|
+
mergeMaps(this.global, global);
|
|
240
|
+
for (const [id, map] of Object.entries(bySession)) {
|
|
241
|
+
mergeMaps(this.bySession[id] ?? (this.bySession[id] = {}), map);
|
|
242
|
+
}
|
|
243
|
+
this.version += 1;
|
|
244
|
+
this.scheduleWrite();
|
|
245
|
+
}
|
|
246
|
+
pruneSessions(liveIds) {
|
|
247
|
+
for (const id of Object.keys(this.bySession)) {
|
|
248
|
+
if (!liveIds.has(id)) delete this.bySession[id];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/** 启动时应用回填结果:只有真正枚举过会话库的结果才有资格 prune,否则会清空全部按会话数据。 */
|
|
252
|
+
applyBackfill(result) {
|
|
253
|
+
if (result.enumerated) {
|
|
254
|
+
this.pruneSessions(new Set(result.scannedIds));
|
|
255
|
+
}
|
|
256
|
+
this.mergeBackfill(result.global, result.bySession);
|
|
257
|
+
this.flush();
|
|
258
|
+
}
|
|
259
|
+
flush() {
|
|
260
|
+
if (!this.dirty) return;
|
|
261
|
+
this.dirty = false;
|
|
262
|
+
this.pruneAll();
|
|
263
|
+
try {
|
|
264
|
+
mkdirSync2(this.dir, { recursive: true });
|
|
265
|
+
this.atomicWrite("global.json", JSON.stringify({ version: 1, days: this.global }));
|
|
266
|
+
this.atomicWrite("sessions.json", JSON.stringify({ version: 1, bySession: this.bySession }));
|
|
267
|
+
} catch (error) {
|
|
268
|
+
console.error("[token-heatmap] store write failed (degraded to memory):", error);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
snapshotGlobal() {
|
|
272
|
+
return this.deepCopy(this.global);
|
|
273
|
+
}
|
|
274
|
+
snapshotSession(id) {
|
|
275
|
+
return this.deepCopy(this.bySession[id] ?? {});
|
|
276
|
+
}
|
|
277
|
+
pruneAll() {
|
|
278
|
+
const cutoff = cutoffKey(Date.now());
|
|
279
|
+
prune(this.global, cutoff);
|
|
280
|
+
for (const map of Object.values(this.bySession)) prune(map, cutoff);
|
|
281
|
+
}
|
|
282
|
+
scheduleWrite() {
|
|
283
|
+
this.dirty = true;
|
|
284
|
+
if (this.timer !== null) return;
|
|
285
|
+
this.timer = setTimeout(() => {
|
|
286
|
+
this.timer = null;
|
|
287
|
+
this.flush();
|
|
288
|
+
}, WRITE_DELAY_MS);
|
|
289
|
+
}
|
|
290
|
+
atomicWrite(name2, content) {
|
|
291
|
+
const target = join2(this.dir, name2);
|
|
292
|
+
const tmp = `${target}.tmp`;
|
|
293
|
+
writeFileSync2(tmp, content, "utf8");
|
|
294
|
+
renameSync(tmp, target);
|
|
295
|
+
}
|
|
296
|
+
deepCopy(map) {
|
|
297
|
+
const out = {};
|
|
298
|
+
for (const [key, value] of Object.entries(map)) out[key] = { ...value };
|
|
299
|
+
return out;
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
// src/index.ts
|
|
304
|
+
var name = "token-heatmap";
|
|
305
|
+
var inject = ["sessionPersistence"];
|
|
306
|
+
function apply(ctx) {
|
|
307
|
+
const dir = dshHomePath("token-heatmap");
|
|
308
|
+
const store = new UsageStore(dir);
|
|
309
|
+
store.load();
|
|
310
|
+
const persistence = ctx.get("sessionPersistence");
|
|
311
|
+
const runner = new BackfillRunner(dir, persistence);
|
|
312
|
+
new TokenHeatmapService(ctx, store, () => runner.meta());
|
|
313
|
+
ctx.on("session/event", (session, event) => {
|
|
314
|
+
if (event.type !== "assistant/message") return;
|
|
315
|
+
const usage = event.data.usage;
|
|
316
|
+
if (usage === void 0) return;
|
|
317
|
+
store.addUsage(
|
|
318
|
+
session.id,
|
|
319
|
+
dayKeyOf(event.time),
|
|
320
|
+
usage.inputTokens,
|
|
321
|
+
usage.outputTokens,
|
|
322
|
+
usage.cacheReadTokens ?? 0,
|
|
323
|
+
usage.cacheWriteTokens ?? 0
|
|
324
|
+
);
|
|
325
|
+
});
|
|
326
|
+
void runner.run().then((result) => {
|
|
327
|
+
store.applyBackfill(result);
|
|
328
|
+
});
|
|
329
|
+
ctx.effect(() => () => store.flush());
|
|
330
|
+
}
|
|
331
|
+
export {
|
|
332
|
+
apply,
|
|
333
|
+
inject,
|
|
334
|
+
name
|
|
335
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-plugin-token-heatmap",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "GitHub-style daily token usage heatmap for DeepSeek Harness Web",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/P-CAmilE/dsh-plugin-token-heatmap.git"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"deepseek",
|
|
12
|
+
"harness",
|
|
13
|
+
"dsh",
|
|
14
|
+
"dsh-plugin",
|
|
15
|
+
"token-usage",
|
|
16
|
+
"heatmap"
|
|
17
|
+
],
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "lib/index.js",
|
|
20
|
+
"types": "lib/types/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./lib/types/index.d.ts",
|
|
24
|
+
"default": "./lib/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./client": {
|
|
27
|
+
"types": "./lib/types/client/index.d.ts",
|
|
28
|
+
"default": "./lib/client.js"
|
|
29
|
+
},
|
|
30
|
+
"./package.json": "./package.json"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"lib",
|
|
34
|
+
"cordis.patch.yml"
|
|
35
|
+
],
|
|
36
|
+
"dsh": {
|
|
37
|
+
"bundle": {
|
|
38
|
+
"patch": "./cordis.patch.yml"
|
|
39
|
+
},
|
|
40
|
+
"client": {
|
|
41
|
+
"inject": [
|
|
42
|
+
"@deepseek-ai/dsh-client-runtime",
|
|
43
|
+
"@deepseek-ai/dsh-api-gateway"
|
|
44
|
+
],
|
|
45
|
+
"platform": "web"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "node build.mjs",
|
|
50
|
+
"prepare": "pnpm build",
|
|
51
|
+
"prepack": "pnpm build",
|
|
52
|
+
"typecheck": "tsc --noEmit",
|
|
53
|
+
"test": "node --import ./test/helpers/ts-decorators-preload.mjs --test \"test/**/*.test.ts\"",
|
|
54
|
+
"test:ui": "vitest run"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
58
|
+
"@deepseek-ai/dsh-api-gateway": "^0.1.1-rc.2",
|
|
59
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
|
|
60
|
+
"@deepseek-ai/dsh-home-paths": "^0.1.1-rc.2",
|
|
61
|
+
"@deepseek-ai/dsh-session": "^0.1.1-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-session-persistence": "^0.1.1-rc.2",
|
|
63
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.1-rc.2",
|
|
64
|
+
"react": "^18.2.0"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@deepseek-ai/cordis": "4.0.1",
|
|
68
|
+
"@deepseek-ai/dsh-api-gateway": "0.1.1-rc.2",
|
|
69
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
70
|
+
"@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
|
|
71
|
+
"@deepseek-ai/dsh-session": "0.1.1-rc.2",
|
|
72
|
+
"@deepseek-ai/dsh-session-persistence": "0.1.1-rc.2",
|
|
73
|
+
"@deepseek-ai/dsh-typert-protocol": "0.1.1-rc.2",
|
|
74
|
+
"@testing-library/react": "^16.3.2",
|
|
75
|
+
"@types/node": "^26.2.0",
|
|
76
|
+
"@types/react": "~18.3.1",
|
|
77
|
+
"@types/react-dom": "~18.3.1",
|
|
78
|
+
"esbuild": "^0.25.0",
|
|
79
|
+
"jsdom": "^29.1.1",
|
|
80
|
+
"react": "18.3.1",
|
|
81
|
+
"react-dom": "18.3.1",
|
|
82
|
+
"typescript": "^5.9.0",
|
|
83
|
+
"vitest": "^4.0.0"
|
|
84
|
+
}
|
|
85
|
+
}
|