dsh-claude-style 0.19.2 → 0.19.3-dev.48
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.en.md +1 -1
- package/docs/CHANGELOG.md +50 -0
- package/docs/STYLE.md +57 -43
- package/lib/assets/cbbadac799d3.js.br +0 -0
- package/lib/assets/d021d0e8b40f.js.br +0 -0
- package/lib/assets/dd2226ba435f.js.br +0 -0
- package/lib/assets/manifest.json +12 -12
- package/lib/client.js +10 -13
- package/lib/host/peakrate.js +5 -0
- package/lib/host/prices-document.js +4 -3
- package/lib/host/prices.js +4 -0
- package/lib/host/routes.js +6 -10
- package/lib/host/search.js +10 -4
- package/lib/host/session-name.js +29 -0
- package/lib/host/usage-fold.js +18 -11
- package/lib/host/usage-ledger.js +7 -4
- package/lib/host/usage-summary.js +1 -3
- package/lib/host/usage.js +8 -8
- package/lib/prices.json +39 -26
- package/package.json +1 -1
- package/lib/assets/37f115eecbe1.js.br +0 -0
- package/lib/assets/9381a21ff2d0.js.br +0 -0
- package/lib/assets/ff0d661c7214.js.br +0 -0
package/lib/host/peakrate.js
CHANGED
|
@@ -24,6 +24,7 @@ function createPeakRate(ctx) {
|
|
|
24
24
|
let loaded = false;
|
|
25
25
|
let timer;
|
|
26
26
|
let inFlight = null;
|
|
27
|
+
let disposed = false;
|
|
27
28
|
let lastAskedAt = 0;
|
|
28
29
|
const warn = (message) => ctx.logger?.warn?.(message);
|
|
29
30
|
function shippedCatalog() {
|
|
@@ -62,6 +63,7 @@ function createPeakRate(ctx) {
|
|
|
62
63
|
async function refresh() {
|
|
63
64
|
let raw;
|
|
64
65
|
for (const url of PEAKRATE_CATALOG_URLS) {
|
|
66
|
+
if (disposed) return false;
|
|
65
67
|
try {
|
|
66
68
|
const controller = new AbortController();
|
|
67
69
|
inFlight = controller;
|
|
@@ -92,6 +94,7 @@ function createPeakRate(ctx) {
|
|
|
92
94
|
warn(`${PACKAGE_NAME}: peak rate source answered a document this build does not understand; keeping the current catalog`);
|
|
93
95
|
return false;
|
|
94
96
|
}
|
|
97
|
+
if (disposed) return false;
|
|
95
98
|
catalog = parsed;
|
|
96
99
|
origin = "remote";
|
|
97
100
|
fetchedAt = Date.now();
|
|
@@ -99,6 +102,7 @@ function createPeakRate(ctx) {
|
|
|
99
102
|
return true;
|
|
100
103
|
}
|
|
101
104
|
function writeCache() {
|
|
105
|
+
if (disposed) return;
|
|
102
106
|
const stored = { fetchedAt, document: catalog };
|
|
103
107
|
writeJsonDocument(ctx, cacheFile, "peak rate cache", stored);
|
|
104
108
|
}
|
|
@@ -134,6 +138,7 @@ function createPeakRate(ctx) {
|
|
|
134
138
|
refresh,
|
|
135
139
|
payload,
|
|
136
140
|
dispose() {
|
|
141
|
+
disposed = true;
|
|
137
142
|
stopTimer();
|
|
138
143
|
if (inFlight !== null) {
|
|
139
144
|
inFlight.abort();
|
|
@@ -131,9 +131,10 @@ function asCatalog(value) {
|
|
|
131
131
|
const out = {};
|
|
132
132
|
for (const [id, line] of Object.entries(raw)) {
|
|
133
133
|
if (typeof line !== "string" || id.trim() === "") continue;
|
|
134
|
-
const parts = line.
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
const parts = line.trim().split(/\s+/u);
|
|
135
|
+
const rates = parts.map(Number);
|
|
136
|
+
if (parts.length !== 3 || !rates.every((candidate) => Number.isFinite(candidate) && candidate >= 0)) continue;
|
|
137
|
+
out[id.trim().toLowerCase()] = rates.join(" ");
|
|
137
138
|
}
|
|
138
139
|
return out;
|
|
139
140
|
}
|
package/lib/host/prices.js
CHANGED
|
@@ -24,6 +24,7 @@ function createPrices(ctx) {
|
|
|
24
24
|
let loaded = false;
|
|
25
25
|
let timer;
|
|
26
26
|
let inFlight = null;
|
|
27
|
+
let disposed = false;
|
|
27
28
|
let lastAskedAt = 0;
|
|
28
29
|
const listeners = /* @__PURE__ */ new Set();
|
|
29
30
|
const warn = (message) => ctx.logger?.warn?.(message);
|
|
@@ -78,6 +79,7 @@ function createPrices(ctx) {
|
|
|
78
79
|
async function refresh() {
|
|
79
80
|
let next = null;
|
|
80
81
|
for (const url of PRICES_URLS) {
|
|
82
|
+
if (disposed) return false;
|
|
81
83
|
try {
|
|
82
84
|
next = await fetchOne(url);
|
|
83
85
|
} catch (error) {
|
|
@@ -89,6 +91,7 @@ function createPrices(ctx) {
|
|
|
89
91
|
warn(`${PACKAGE_NAME}: no price source answered a document this build understands; keeping the current one`);
|
|
90
92
|
return false;
|
|
91
93
|
}
|
|
94
|
+
if (disposed) return false;
|
|
92
95
|
document = next;
|
|
93
96
|
origin = "remote";
|
|
94
97
|
fetchedAt = Date.now();
|
|
@@ -135,6 +138,7 @@ function createPrices(ctx) {
|
|
|
135
138
|
return () => listeners.delete(listener);
|
|
136
139
|
},
|
|
137
140
|
dispose() {
|
|
141
|
+
disposed = true;
|
|
138
142
|
stopTimer();
|
|
139
143
|
listeners.clear();
|
|
140
144
|
if (inFlight !== null) {
|
package/lib/host/routes.js
CHANGED
|
@@ -174,6 +174,7 @@ import { createPeakRate } from "./peakrate.js";
|
|
|
174
174
|
import { createPrices } from "./prices.js";
|
|
175
175
|
import { QUERY_MAX, createSessionSearch } from "./search.js";
|
|
176
176
|
import { createSessionCost } from "./session-cost.js";
|
|
177
|
+
import { sessionDirectoryName } from "./session-name.js";
|
|
177
178
|
import { createUsage } from "./usage.js";
|
|
178
179
|
var COPY_FILE = "model-descriptions.json";
|
|
179
180
|
var FONT_FILES = {
|
|
@@ -187,16 +188,6 @@ var FONT_FILES = {
|
|
|
187
188
|
};
|
|
188
189
|
var ASSETS_PATH = `${ROUTE_PREFIX}/assets/`;
|
|
189
190
|
var DELETE_BODY_MAX = 4096;
|
|
190
|
-
function sessionDirectoryName(id) {
|
|
191
|
-
if (id === ".") return "~002E";
|
|
192
|
-
if (id === "..") return "~002E~002E";
|
|
193
|
-
let name = "";
|
|
194
|
-
for (let index = 0; index < id.length; index += 1) {
|
|
195
|
-
const unit = id.charAt(index);
|
|
196
|
-
name += unit !== "~" && /^[A-Za-z0-9._-]$/.test(unit) ? unit : `~${id.charCodeAt(index).toString(16).toUpperCase().padStart(4, "0")}`;
|
|
197
|
-
}
|
|
198
|
-
return name;
|
|
199
|
-
}
|
|
200
191
|
var SESSION_ID_RE = /^[A-Za-z0-9._\-:@]{1,200}$/;
|
|
201
192
|
function sessionIsLive(ctx, sessionId) {
|
|
202
193
|
const sessions = ctx.get("sessions");
|
|
@@ -263,6 +254,10 @@ async function deleteSession(ctx, req, res) {
|
|
|
263
254
|
sendJson(res, 403, { ok: false, error: "session directory outside the sessions root" });
|
|
264
255
|
return;
|
|
265
256
|
}
|
|
257
|
+
if (sessionIsLive(ctx, sessionId)) {
|
|
258
|
+
sendJson(res, 409, { ok: false, error: "session is open" });
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
266
261
|
rmSync(dir, { recursive: true, force: true });
|
|
267
262
|
await unarchiveSession(ctx, sessionId);
|
|
268
263
|
sendJson(res, 200, { ok: true, ghost: false });
|
|
@@ -309,6 +304,7 @@ function registerRoutes(ctx, scope) {
|
|
|
309
304
|
path: ROUTE_PREFIX,
|
|
310
305
|
handler: (req, res) => {
|
|
311
306
|
if (methodRefused(req, res, ["GET", "HEAD"])) return;
|
|
307
|
+
if (fenceRefused(ctx, req, res)) return;
|
|
312
308
|
const sub = new URL(req.url ?? "/", "http://x").pathname.slice(ROUTE_PREFIX.length);
|
|
313
309
|
if (sub === `/${COPY_FILE}`) {
|
|
314
310
|
sendFile(res, req.method ?? "GET", file, {
|
package/lib/host/search.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
var PACKAGE_NAME = "dsh-claude-style";
|
|
3
3
|
|
|
4
4
|
// packages/host/src/search.ts
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
5
6
|
import { cachePath, readJsonDocument, writeJsonDocument } from "./cache-file.js";
|
|
6
7
|
|
|
7
8
|
// packages/engine/node/session-events.ts
|
|
@@ -103,8 +104,9 @@ function createSessionSearch(ctx) {
|
|
|
103
104
|
let refreshingStore = false;
|
|
104
105
|
let stored = null;
|
|
105
106
|
let listedAt = 0;
|
|
107
|
+
let disposed = false;
|
|
106
108
|
function cacheFile(sessionId) {
|
|
107
|
-
return cachePath(ctx, "search", `${sessionId}.json`);
|
|
109
|
+
return cachePath(ctx, "search", `${createHash("sha256").update(sessionId).digest("hex")}.json`);
|
|
108
110
|
}
|
|
109
111
|
function readCached(sessionId) {
|
|
110
112
|
const parsed = readJsonDocument(ctx, cacheFile(sessionId), "session search cache");
|
|
@@ -121,6 +123,7 @@ function createSessionSearch(ctx) {
|
|
|
121
123
|
return { revision: document.revision, lastSeq: Number(document.lastSeq), messages };
|
|
122
124
|
}
|
|
123
125
|
function adopt(sessionId, entry, force) {
|
|
126
|
+
if (disposed) return;
|
|
124
127
|
cache.set(sessionId, entry);
|
|
125
128
|
lower.set(sessionId, entry.messages.map((message) => message.text.toLowerCase()));
|
|
126
129
|
const now = Date.now();
|
|
@@ -134,6 +137,7 @@ function createSessionSearch(ctx) {
|
|
|
134
137
|
});
|
|
135
138
|
}
|
|
136
139
|
function forget(sessionId) {
|
|
140
|
+
if (disposed) return;
|
|
137
141
|
cache.delete(sessionId);
|
|
138
142
|
lower.delete(sessionId);
|
|
139
143
|
writtenAt.delete(sessionId);
|
|
@@ -141,10 +145,11 @@ function createSessionSearch(ctx) {
|
|
|
141
145
|
}
|
|
142
146
|
async function rebuild(sessionId, revision) {
|
|
143
147
|
const events = await readEvents(ctx, PACKAGE_NAME, sessionId, "content search");
|
|
144
|
-
|
|
145
|
-
|
|
148
|
+
if (disposed) return;
|
|
149
|
+
if (events === null) return;
|
|
150
|
+
const last = events[events.length - 1];
|
|
146
151
|
const lastSeq = typeof last?.seq === "number" ? last.seq + 1 : 0;
|
|
147
|
-
adopt(sessionId, { revision, lastSeq, messages }, false);
|
|
152
|
+
adopt(sessionId, { revision, lastSeq, messages: messagesOf(events) }, false);
|
|
148
153
|
}
|
|
149
154
|
async function refresh(store) {
|
|
150
155
|
const persistence = ctx.get("sessionPersistence");
|
|
@@ -244,6 +249,7 @@ function createSessionSearch(ctx) {
|
|
|
244
249
|
return { sessions: hits.slice(0, SESSION_LIMIT), scanned: cache.size };
|
|
245
250
|
}
|
|
246
251
|
function dispose() {
|
|
252
|
+
disposed = true;
|
|
247
253
|
cache.clear();
|
|
248
254
|
lower.clear();
|
|
249
255
|
writtenAt.clear();
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// packages/host/src/session-name.ts
|
|
2
|
+
var ESCAPE = /^[0-9A-F]{4}$/;
|
|
3
|
+
function sessionDirectoryName(id) {
|
|
4
|
+
if (id === ".") return "~002E";
|
|
5
|
+
if (id === "..") return "~002E~002E";
|
|
6
|
+
let name = "";
|
|
7
|
+
for (let index = 0; index < id.length; index += 1) {
|
|
8
|
+
const unit = id.charAt(index);
|
|
9
|
+
name += unit !== "~" && /^[A-Za-z0-9._-]$/.test(unit) ? unit : `~${id.charCodeAt(index).toString(16).toUpperCase().padStart(4, "0")}`;
|
|
10
|
+
}
|
|
11
|
+
return name;
|
|
12
|
+
}
|
|
13
|
+
function sessionIdFromDirectoryName(name) {
|
|
14
|
+
let id = "";
|
|
15
|
+
for (let index = 0; index < name.length; index += 1) {
|
|
16
|
+
const hex = name.charAt(index) === "~" ? name.slice(index + 1, index + 5) : "";
|
|
17
|
+
if (ESCAPE.test(hex)) {
|
|
18
|
+
id += String.fromCharCode(Number.parseInt(hex, 16));
|
|
19
|
+
index += 4;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
id += name.charAt(index);
|
|
23
|
+
}
|
|
24
|
+
return id;
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
sessionDirectoryName,
|
|
28
|
+
sessionIdFromDirectoryName
|
|
29
|
+
};
|
package/lib/host/usage-fold.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// packages/host/src/usage-fold.ts
|
|
2
|
-
import { existsSync
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { readdir, stat } from "node:fs/promises";
|
|
3
4
|
import { join } from "node:path";
|
|
5
|
+
import { sessionIdFromDirectoryName } from "./session-name.js";
|
|
4
6
|
import { BUCKET_KEYS, addBuckets, emptyBuckets } from "./usage-ledger.js";
|
|
5
7
|
var SESSION_LOG = /^session(?:\.v([1-9][0-9]*))?\.jsonl(?:\.zstd)?$/i;
|
|
6
8
|
function dayKey(time) {
|
|
@@ -101,10 +103,10 @@ function foldSession(events) {
|
|
|
101
103
|
}
|
|
102
104
|
return { days, hours };
|
|
103
105
|
}
|
|
104
|
-
function newestLog(dir) {
|
|
106
|
+
async function newestLog(dir) {
|
|
105
107
|
let entries;
|
|
106
108
|
try {
|
|
107
|
-
entries =
|
|
109
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
108
110
|
} catch (error) {
|
|
109
111
|
if (error.code === "ENOENT") return null;
|
|
110
112
|
throw error;
|
|
@@ -122,27 +124,32 @@ function newestLog(dir) {
|
|
|
122
124
|
}
|
|
123
125
|
if (best === null) return null;
|
|
124
126
|
const path = join(dir, best.name);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
try {
|
|
128
|
+
const info = await stat(path);
|
|
129
|
+
return { path, size: info.size, mtimeMs: info.mtimeMs };
|
|
130
|
+
} catch (error) {
|
|
131
|
+
if (error.code === "ENOENT") return null;
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
128
134
|
}
|
|
129
|
-
function listSessionLogs(root) {
|
|
135
|
+
async function listSessionLogs(root) {
|
|
130
136
|
const out = [];
|
|
131
137
|
if (!existsSync(root)) return out;
|
|
132
|
-
for (const project of
|
|
138
|
+
for (const project of await readdir(root, { withFileTypes: true })) {
|
|
133
139
|
if (!project.isDirectory()) continue;
|
|
134
140
|
let sessions;
|
|
135
141
|
try {
|
|
136
|
-
sessions =
|
|
142
|
+
sessions = await readdir(join(root, project.name), { withFileTypes: true });
|
|
137
143
|
} catch (error) {
|
|
138
144
|
if (error.code === "ENOENT") continue;
|
|
139
145
|
throw error;
|
|
140
146
|
}
|
|
141
147
|
for (const session of sessions) {
|
|
142
148
|
if (!session.isDirectory()) continue;
|
|
143
|
-
const log = newestLog(join(root, project.name, session.name));
|
|
149
|
+
const log = await newestLog(join(root, project.name, session.name));
|
|
144
150
|
if (log === null) continue;
|
|
145
|
-
|
|
151
|
+
const storedName = session.name;
|
|
152
|
+
out.push({ id: sessionIdFromDirectoryName(storedName), storedName, ...log });
|
|
146
153
|
}
|
|
147
154
|
}
|
|
148
155
|
return out;
|
package/lib/host/usage-ledger.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// packages/contracts/src/package.ts
|
|
2
|
+
var PACKAGE_NAME = "dsh-claude-style";
|
|
3
|
+
|
|
1
4
|
// packages/host/src/usage-ledger.ts
|
|
2
5
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
6
|
import { join } from "node:path";
|
|
@@ -21,14 +24,14 @@ function addBuckets(target, buckets, sign) {
|
|
|
21
24
|
}
|
|
22
25
|
target.calls += sign * (Number.isFinite(Number(buckets?.calls)) ? Number(buckets.calls) : 0);
|
|
23
26
|
}
|
|
24
|
-
function readLedger(home) {
|
|
27
|
+
function readLedger(home, logger) {
|
|
25
28
|
const file = join(home, "storages", "cost-meter", "ledger.json");
|
|
26
29
|
if (!existsSync(file)) return null;
|
|
27
|
-
const raw = readFileSync(file, "utf8");
|
|
28
30
|
let parsed;
|
|
29
31
|
try {
|
|
30
|
-
parsed = JSON.parse(
|
|
31
|
-
} catch {
|
|
32
|
+
parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
33
|
+
} catch (error) {
|
|
34
|
+
logger?.warn?.(`${PACKAGE_NAME}: cost-meter ledger unreadable, folding the session logs alone: ${error.message}`);
|
|
32
35
|
return null;
|
|
33
36
|
}
|
|
34
37
|
if (parsed === null || typeof parsed !== "object") return null;
|
|
@@ -96,15 +96,13 @@ function summarize(days, sessionCount, source, hours, window) {
|
|
|
96
96
|
function mergeLedgerFold(ledgerDays, sessions) {
|
|
97
97
|
const days = /* @__PURE__ */ new Map();
|
|
98
98
|
const sessionIds = /* @__PURE__ */ new Set();
|
|
99
|
-
let lastLedgerDay = null;
|
|
100
99
|
for (const [date, buckets] of ledgerDays ?? []) {
|
|
101
100
|
days.set(date, buckets);
|
|
102
|
-
if (lastLedgerDay === null || date > lastLedgerDay) lastLedgerDay = date;
|
|
103
101
|
for (const id of buckets.sessionIds ?? []) sessionIds.add(id);
|
|
104
102
|
}
|
|
105
103
|
let folded = false;
|
|
106
104
|
for (const [date, buckets] of mergeSessions(sessions)) {
|
|
107
|
-
if (
|
|
105
|
+
if (days.has(date)) continue;
|
|
108
106
|
days.set(date, buckets);
|
|
109
107
|
folded = true;
|
|
110
108
|
for (const id of buckets.sessionIds ?? []) sessionIds.add(id);
|
package/lib/host/usage.js
CHANGED
|
@@ -98,10 +98,10 @@ function createUsage(ctx) {
|
|
|
98
98
|
let failed = 0;
|
|
99
99
|
let firstFailure = null;
|
|
100
100
|
for (const log of logs) {
|
|
101
|
-
const stored = record.sessions.get(log.
|
|
101
|
+
const stored = record.sessions.get(log.storedName);
|
|
102
102
|
const fingerprint = stored?.fingerprint;
|
|
103
103
|
if (stored !== void 0 && fingerprint !== void 0 && fingerprint.size === log.size && fingerprint.mtimeMs === log.mtimeMs) {
|
|
104
|
-
sessions.set(log.
|
|
104
|
+
sessions.set(log.storedName, stored);
|
|
105
105
|
continue;
|
|
106
106
|
}
|
|
107
107
|
let events;
|
|
@@ -110,15 +110,15 @@ function createUsage(ctx) {
|
|
|
110
110
|
} catch (error) {
|
|
111
111
|
failed += 1;
|
|
112
112
|
firstFailure = firstFailure ?? `${log.id}: ${messageOf(error)}`;
|
|
113
|
-
if (stored !== void 0) sessions.set(log.
|
|
113
|
+
if (stored !== void 0) sessions.set(log.storedName, stored);
|
|
114
114
|
continue;
|
|
115
115
|
}
|
|
116
116
|
if (events === null) {
|
|
117
117
|
failed += 1;
|
|
118
|
-
if (stored !== void 0) sessions.set(log.
|
|
118
|
+
if (stored !== void 0) sessions.set(log.storedName, stored);
|
|
119
119
|
continue;
|
|
120
120
|
}
|
|
121
|
-
sessions.set(log.
|
|
121
|
+
sessions.set(log.storedName, { fingerprint: { size: log.size, mtimeMs: log.mtimeMs }, days: foldSession(events).days });
|
|
122
122
|
read += 1;
|
|
123
123
|
}
|
|
124
124
|
if (firstFailure !== null) {
|
|
@@ -127,7 +127,7 @@ function createUsage(ctx) {
|
|
|
127
127
|
for (const [id, stored] of record.sessions) {
|
|
128
128
|
if (!sessions.has(id) && stored.days.size > 0) sessions.set(id, { days: stored.days });
|
|
129
129
|
}
|
|
130
|
-
const recorded = record.writable && (record.mustWrite || recordChanged(record.sessions, sessions, read)) ? writeRecord(ctx, sessions, new Set(logs.map((log) => log.
|
|
130
|
+
const recorded = !disposed && record.writable && (record.mustWrite || recordChanged(record.sessions, sessions, read)) ? writeRecord(ctx, sessions, new Set(logs.map((log) => log.storedName))) : sessions;
|
|
131
131
|
const merge = mergeLedgerFold(ledgerDays, recorded);
|
|
132
132
|
const source = ledgerDays === null ? LOCAL_SOURCE : merge.folded ? `${LEDGER_SOURCE}+${LOCAL_SOURCE}` : LEDGER_SOURCE;
|
|
133
133
|
const summary = summarize(
|
|
@@ -144,8 +144,8 @@ function createUsage(ctx) {
|
|
|
144
144
|
}
|
|
145
145
|
async function compute(publish) {
|
|
146
146
|
const root = resolve(join2(home(), "sessions"));
|
|
147
|
-
const logs = listSessionLogs(root);
|
|
148
|
-
const ledgerDays = readLedger(home());
|
|
147
|
+
const logs = await listSessionLogs(root);
|
|
148
|
+
const ledgerDays = readLedger(home(), ctx.logger);
|
|
149
149
|
if (ledgerDays !== null && ledgerDays.size > 0) {
|
|
150
150
|
const sessionIds = /* @__PURE__ */ new Set();
|
|
151
151
|
for (const buckets of ledgerDays.values()) {
|
package/lib/prices.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"updatedAt": "2026-10-
|
|
4
|
-
"capturedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-25",
|
|
4
|
+
"capturedAt": "2026-10-25T08:22:19.000Z",
|
|
5
5
|
"source": {
|
|
6
6
|
"zh": "https://api-docs.deepseek.com/zh-cn/quick_start/pricing/",
|
|
7
7
|
"en": "https://api-docs.deepseek.com/quick_start/pricing/"
|
|
@@ -247,7 +247,7 @@
|
|
|
247
247
|
"bge-multilingual-gemma2": "0.11215 0.11215 0",
|
|
248
248
|
"bge-reranker-v2-m3": "0.01 0.01 0",
|
|
249
249
|
"bge_multilingual_gemma2": "0.08 0.08 0",
|
|
250
|
-
"bielik-11b-v3.0-instruct": "0.
|
|
250
|
+
"bielik-11b-v3.0-instruct": "0.575 0.575 0.575",
|
|
251
251
|
"brick-complexity-pro": "0.12 0.12 0.46",
|
|
252
252
|
"c4ai-aya-expanse-32b": "0.5 0.5 1.5",
|
|
253
253
|
"ca.amazon.nova-lite-v1:0": "0.064 0.016 0.256",
|
|
@@ -510,7 +510,7 @@
|
|
|
510
510
|
"deepseek-v4-1-flash": "0.3 0.03 1.2",
|
|
511
511
|
"deepseek-v4-1-flash-1017": "0.3 0.15375 1.2",
|
|
512
512
|
"deepseek-v4-1-flash-uncensored": "0.33 0.00825 1.32",
|
|
513
|
-
"deepseek-v4-flash": "0.14 0.
|
|
513
|
+
"deepseek-v4-flash": "0.14 0.022 0.28",
|
|
514
514
|
"deepseek-v4-flash-0423": "0.14 0.028 0.28",
|
|
515
515
|
"deepseek-v4-flash-0423:thinking": "0.14 0.028 0.28",
|
|
516
516
|
"deepseek-v4-flash-0731": "0.142 0.028 0.3",
|
|
@@ -546,8 +546,8 @@
|
|
|
546
546
|
"deepseek-v4.1-flash-fast": "0.425 0.014 1.8",
|
|
547
547
|
"deepseek-v4.1-flash-flex": "0.0975 0.00975 0.39",
|
|
548
548
|
"deepseek-v4.1-flash-marathon": "0.14 0.0028 0.28",
|
|
549
|
-
"deepseek-v4.1-flash-uncensored": "0.
|
|
550
|
-
"deepseek-v4.1-flash-uncensored:thinking": "0.
|
|
549
|
+
"deepseek-v4.1-flash-uncensored": "0.33 0.00825 1.32",
|
|
550
|
+
"deepseek-v4.1-flash-uncensored:thinking": "0.33 0.00825 1.32",
|
|
551
551
|
"deepseek-v4.1-flash:1017": "0.15 0.003 0.6",
|
|
552
552
|
"deepseek-v4.1-flash:fast": "0.6 0.012 2.4",
|
|
553
553
|
"deepseek-v4.1-flash:peft:262144": "0.6 0.12 3.6",
|
|
@@ -570,9 +570,9 @@
|
|
|
570
570
|
"diffusiongemma": "0.05 0.025 0.15",
|
|
571
571
|
"dola-seed-2.0-code": "0.4 0.4 2.4",
|
|
572
572
|
"dola-seed-2.0-code-preview": "0.5 0.5 3",
|
|
573
|
-
"dola-seed-2.0-lite": "0.
|
|
574
|
-
"dola-seed-2.0-mini": "0.
|
|
575
|
-
"dola-seed-2.0-pro": "0.
|
|
573
|
+
"dola-seed-2.0-lite": "0.31 0.31 2.5",
|
|
574
|
+
"dola-seed-2.0-mini": "0.12 0.12 0.5",
|
|
575
|
+
"dola-seed-2.0-pro": "0.63 0.63 3.79",
|
|
576
576
|
"dolphin-mistral-24b-venice-edition": "0.2 0.2 0.9",
|
|
577
577
|
"doubao-1.5-pro-256k": "0.799 0.3995 1.445",
|
|
578
578
|
"doubao-1.5-pro-32k": "0.125121 0.091546 0.312378",
|
|
@@ -766,6 +766,7 @@
|
|
|
766
766
|
"gemma-4": "2 0.5 5",
|
|
767
767
|
"gemma-4-12b-it": "0.075 0.0625 0.275",
|
|
768
768
|
"gemma-4-12b-it-semancer": "0.05 0.025 0.25",
|
|
769
|
+
"gemma-4-12b-it-starry-ocean": "0.05 0.025 0.25",
|
|
769
770
|
"gemma-4-12b-it-station-keeper": "0.05 0.025 0.25",
|
|
770
771
|
"gemma-4-26b-a4b": "0.05 0.025 0.29",
|
|
771
772
|
"gemma-4-26b-a4b-it": "0.1 0.07 0.34",
|
|
@@ -784,10 +785,18 @@
|
|
|
784
785
|
"gemma-4-26b-a4b-meromero:thinking": "0.12 0.06 0.38",
|
|
785
786
|
"gemma-4-26b-a4b-uncensored": "0.15 0.075 0.7",
|
|
786
787
|
"gemma-4-31b": "0.144 0.0144 0.42",
|
|
788
|
+
"gemma-4-31b-agares-v1": "0.306 0.306 0.306",
|
|
789
|
+
"gemma-4-31b-animus-v14.1": "0.306 0.306 0.306",
|
|
790
|
+
"gemma-4-31b-assguard": "0.306 0.306 0.306",
|
|
787
791
|
"gemma-4-31b-claude-4.6-opus-reasoning-distilled": "0.306 0.0306 0.306",
|
|
788
792
|
"gemma-4-31b-cognitive-unshackled": "0.306 0.153 0.306",
|
|
793
|
+
"gemma-4-31b-dark-gemistry": "0.306 0.306 0.306",
|
|
789
794
|
"gemma-4-31b-darkidol": "0.306 0.153 0.306",
|
|
795
|
+
"gemma-4-31b-fabled": "0.306 0.306 0.306",
|
|
790
796
|
"gemma-4-31b-garnetv2": "0.306 0.153 0.306",
|
|
797
|
+
"gemma-4-31b-gembrain-uncensored-heretic": "0.306 0.306 0.306",
|
|
798
|
+
"gemma-4-31b-gembrain-x-core": "0.306 0.306 0.306",
|
|
799
|
+
"gemma-4-31b-isometry-rp": "0.306 0.306 0.306",
|
|
791
800
|
"gemma-4-31b-it": "0.14 0.14 0.4",
|
|
792
801
|
"gemma-4-31b-it-darkidol": "0.1 0.05 0.45",
|
|
793
802
|
"gemma-4-31b-it-fabled": "0.1 0.05 0.45",
|
|
@@ -798,13 +807,16 @@
|
|
|
798
807
|
"gemma-4-31b-it-novelist": "0.1 0.05 0.45",
|
|
799
808
|
"gemma-4-31b-it-scarlet": "0.1 0.05 0.45",
|
|
800
809
|
"gemma-4-31b-it:thinking": "0.1 0.1 0.34",
|
|
810
|
+
"gemma-4-31b-k1-v5": "0.306 0.306 0.306",
|
|
811
|
+
"gemma-4-31b-meromero": "0.306 0.306 0.306",
|
|
801
812
|
"gemma-4-31b-meromero-v2": "0.1 0.05 0.45",
|
|
802
813
|
"gemma-4-31b-meromero-v2:thinking": "0.1 0.05 0.45",
|
|
814
|
+
"gemma-4-31b-novelist": "0.306 0.306 0.306",
|
|
803
815
|
"gemma-4-31b-queen": "0.306 0.153 0.306",
|
|
816
|
+
"gemma-4-31b-sdft-heretic-rp": "0.306 0.306 0.306",
|
|
817
|
+
"gemma-4-31b-styletune": "0.306 0.306 0.306",
|
|
804
818
|
"gemma-4-31b-turbo-tee": "0.12 0.012 0.37",
|
|
805
|
-
"gemma-4-dark-thoughts-v2-31b": "0.1 0.05 0.45",
|
|
806
819
|
"gemma-4-e4b-it": "0.02 0.02 0.1",
|
|
807
|
-
"gemma-4-giftige-blume-31b-v2": "0.1 0.05 0.45",
|
|
808
820
|
"gemma-4-uncensored": "0.1625 0.1625 0.5",
|
|
809
821
|
"gemma-sea-lion-v4-27b-it": "0.351 0.351 0.555",
|
|
810
822
|
"gemma2-9b-it": "0.01 0.01 0.03",
|
|
@@ -813,7 +825,6 @@
|
|
|
813
825
|
"gemma4-31b": "0.4 0.4 1",
|
|
814
826
|
"gemma4-31b-splituntied": "0.1 0.05 0.3",
|
|
815
827
|
"gemma4-31b:thinking": "0.4 0.4 1",
|
|
816
|
-
"gemma4-gutenberg-31b": "0.1 0.05 0.45",
|
|
817
828
|
"gemma4:31b": "0.14 0.05 0.4",
|
|
818
829
|
"gliguard-llmguardrails-300m": "0.15 0.15 0.15",
|
|
819
830
|
"gliguard-pii-multi": "0.15 0.15 0.15",
|
|
@@ -836,7 +847,7 @@
|
|
|
836
847
|
"glm-4.1v-thinking-flashx": "0.3 0.15 0.3",
|
|
837
848
|
"glm-4.5": "0.6 0.11 2.2",
|
|
838
849
|
"glm-4.5-air": "0.14 0.03 0.89637",
|
|
839
|
-
"glm-4.5-air:thinking": "0.
|
|
850
|
+
"glm-4.5-air:thinking": "0.13 0.025 0.85",
|
|
840
851
|
"glm-4.5-airx": "1.1 0.22 4.5",
|
|
841
852
|
"glm-4.5-fp8": "0.2 0.2 0.8",
|
|
842
853
|
"glm-4.5-x": "2.2 0.45 8.9",
|
|
@@ -926,8 +937,8 @@
|
|
|
926
937
|
"glm-5v-turbo": "1.2 0.24 4",
|
|
927
938
|
"glm-5v-turbo:thinking": "1.2 0.24 4",
|
|
928
939
|
"glm-fast-latest": "2.1 0.39 6.6",
|
|
929
|
-
"glm-flash-latest": "0.
|
|
930
|
-
"glm-latest": "0.6 0.1733
|
|
940
|
+
"glm-flash-latest": "0.0959 0.03 0.2885",
|
|
941
|
+
"glm-latest": "0.6 0.1733 4.3843",
|
|
931
942
|
"glm-z1-9b-0414": "0.2 0.1 0.2",
|
|
932
943
|
"glm-z1-airx": "0.7 0.35 0.7",
|
|
933
944
|
"glm5.2": "2.31 2.31 6",
|
|
@@ -1134,6 +1145,7 @@
|
|
|
1134
1145
|
"granite-4-h-small": "0.0636 0.0636 0.265",
|
|
1135
1146
|
"granite-4.0-h-micro": "0.017 0.017 0.112",
|
|
1136
1147
|
"granite-4.2-8b": "0.06 0.015 0.25",
|
|
1148
|
+
"grayline-qwen3-8b": "0.3 0.3 0.3",
|
|
1137
1149
|
"green-l": "0.285 0.285 0.912",
|
|
1138
1150
|
"green-l-raw": "0.285 0.285 0.912",
|
|
1139
1151
|
"green-r": "0.399 0.399 1.083",
|
|
@@ -1282,11 +1294,11 @@
|
|
|
1282
1294
|
"kimi-k3.1-pro-highspeed": "4 0.2 20",
|
|
1283
1295
|
"kimi-k3:fast": "6 0.6 30",
|
|
1284
1296
|
"kimi-k3@eu": "3 0.45 15",
|
|
1285
|
-
"kimi-latest": "1.2 0.
|
|
1297
|
+
"kimi-latest": "1.2 0.19 8.94",
|
|
1286
1298
|
"kloker": "0.23 0.23 1.16",
|
|
1287
1299
|
"kloker-integration-architect": "0.23 0.23 1.16",
|
|
1288
1300
|
"kloker-integration-developer": "0.23 0.23 1.16",
|
|
1289
|
-
"kolibri-1": "0.
|
|
1301
|
+
"kolibri-1": "0.1635 0.089 0.574",
|
|
1290
1302
|
"l3-8b-stheno-v3.2": "0.2006 0.1003 0.2006",
|
|
1291
1303
|
"l3-lunaris-8b": "0.04 0.04 0.05",
|
|
1292
1304
|
"l3.1-70b-celeste-v0.1-bf16": "0.493 0.2465 0.493",
|
|
@@ -1303,7 +1315,7 @@
|
|
|
1303
1315
|
"laguna-s-2.1:thinking": "0.1 0.01 0.2",
|
|
1304
1316
|
"laguna-xs-2.1": "0.08 0.04 0.16",
|
|
1305
1317
|
"large": "0.6 0.15 2",
|
|
1306
|
-
"lfm-2.5-2.6b": "0.
|
|
1318
|
+
"lfm-2.5-2.6b": "0.35 0.04 0.5",
|
|
1307
1319
|
"lfm-2.5-24b-a2b": "0.05 0.025 0.7",
|
|
1308
1320
|
"lfm2-24b-a2b": "0.03 0.03 0.12",
|
|
1309
1321
|
"lfm2.5-24b-a2b": "0.05 0.025 0.7",
|
|
@@ -1735,8 +1747,7 @@
|
|
|
1735
1747
|
"openai.gpt-oss-safeguard-20b": "0.07 0.07 0.2",
|
|
1736
1748
|
"openai.gpt-oss-safeguard-20b@us": "0.07 0.07 0.2",
|
|
1737
1749
|
"openreasoning-nemotron-32b": "0.1 0.05 0.4",
|
|
1738
|
-
"
|
|
1739
|
-
"ornith-1.5-122b": "0.2 0.05 0.8",
|
|
1750
|
+
"ornith-1.5-122b": "0.26 0.07 2.08",
|
|
1740
1751
|
"ornith-1.5-35b-a3b": "0.1 0.03 0.4",
|
|
1741
1752
|
"ornith-1.5-35b-a3b:thinking": "0.1 0.05 0.4",
|
|
1742
1753
|
"osmosis-structure-0.6b": "0.1 0.1 0.5",
|
|
@@ -1801,6 +1812,7 @@
|
|
|
1801
1812
|
"qwen-plus-character": "0.115 0.115 0.287",
|
|
1802
1813
|
"qwen-plus-character-ja": "0.5 0.5 1.4",
|
|
1803
1814
|
"qwen-plus-latest": "0.4 0.08 1.2",
|
|
1815
|
+
"qwen-sea-lion-v4-32b-it": "0.3 0.3 0.6",
|
|
1804
1816
|
"qwen-turbo": "0.04699 0.034234 0.09",
|
|
1805
1817
|
"qwen-vl-max": "0.23 0.138 0.58",
|
|
1806
1818
|
"qwen-vl-max-2025-01-25": "0.434783 0.434783 1.304348",
|
|
@@ -1821,7 +1833,7 @@
|
|
|
1821
1833
|
"qwen2.5-coder-32b-instruct": "0.4303 0.38015 0.6003",
|
|
1822
1834
|
"qwen2.5-coder-7b-fast": "0.03 0.03 0.09",
|
|
1823
1835
|
"qwen2.5-vl-32b-instruct": "0.125 0.1125 0.41",
|
|
1824
|
-
"qwen2.5-vl-72b-instruct": "0.
|
|
1836
|
+
"qwen2.5-vl-72b-instruct": "0.8 0.69989 1",
|
|
1825
1837
|
"qwen3-14b": "0.08 0.076 0.24",
|
|
1826
1838
|
"qwen3-235b-a22b": "0.287 0.287 1.147",
|
|
1827
1839
|
"qwen3-235b-a22b-2507": "0.09 0.09 0.55",
|
|
@@ -1910,7 +1922,10 @@
|
|
|
1910
1922
|
"qwen3.5-122b-a10b-fp8": "0.5 0.5 3.97",
|
|
1911
1923
|
"qwen3.5-122b-a10b:thinking": "0.26 0.103788 2.08",
|
|
1912
1924
|
"qwen3.5-27b": "0.28 0.265 2.28",
|
|
1925
|
+
"qwen3.5-27b-blossom-v6.4-derestricted": "0.306 0.306 0.306",
|
|
1913
1926
|
"qwen3.5-27b-bluestar-v3-derestricted": "0.306 0.153 0.306",
|
|
1927
|
+
"qwen3.5-27b-claude-4.6-opus-reasoning-distilled-derestricted": "0.306 0.0306 0.306",
|
|
1928
|
+
"qwen3.5-27b-claude-4.6-opus-reasoning-distilled-derestricted-lite": "0.306 0.0306 0.306",
|
|
1914
1929
|
"qwen3.5-27b-queen-derestricted": "0.306 0.153 0.306",
|
|
1915
1930
|
"qwen3.5-27b:thinking": "0.25 0.135 2",
|
|
1916
1931
|
"qwen3.5-2b": "0.02 0.02 0.1",
|
|
@@ -1957,7 +1972,7 @@
|
|
|
1957
1972
|
"qwen3.8-2.4t-a95b": "2 0.25 6",
|
|
1958
1973
|
"qwen3.8-2.4t-a95b-nvfp4": "2 0.2 6",
|
|
1959
1974
|
"qwen3.8-2.4t-a95b@eu": "2.5 0.63 6",
|
|
1960
|
-
"qwen3.8-27b": "0.
|
|
1975
|
+
"qwen3.8-27b": "0.4 0.1 3",
|
|
1961
1976
|
"qwen3.8-27b-antislop": "0.1 0.05 0.6",
|
|
1962
1977
|
"qwen3.8-27b-cybersecurity": "0.1 0.05 0.6",
|
|
1963
1978
|
"qwen3.8-27b-darkidol": "0.1 0.05 0.6",
|
|
@@ -1970,8 +1985,6 @@
|
|
|
1970
1985
|
"qwen3.8-27b-kiwen": "0.1 0.05 0.6",
|
|
1971
1986
|
"qwen3.8-27b-novelist": "0.1 0.05 0.6",
|
|
1972
1987
|
"qwen3.8-27b-nvfp4": "0.25 0.04 2.09",
|
|
1973
|
-
"qwen3.8-27b-obliterated": "0.25 0.225 1.75",
|
|
1974
|
-
"qwen3.8-27b-obliterated:thinking": "0.25 0.225 1.75",
|
|
1975
1988
|
"qwen3.8-27b-queen": "0.25 0.125 1.5",
|
|
1976
1989
|
"qwen3.8-27b-swift": "0.1 0.05 0.6",
|
|
1977
1990
|
"qwen3.8-27b-synthia": "0.1 0.05 0.6",
|
|
@@ -2014,7 +2027,6 @@
|
|
|
2014
2027
|
"sarvam-105b": "0.054 0.0336 0.2124",
|
|
2015
2028
|
"scaledown-extract-1": "0.05 0.05 0",
|
|
2016
2029
|
"scaledown-summarize-1": "0.05 0.05 0",
|
|
2017
|
-
"schattenblume-31b": "0.1 0.05 0.45",
|
|
2018
2030
|
"schematron-v2-small": "0.05 0.05 0.23",
|
|
2019
2031
|
"schematron-v2-turbo": "0.03 0.03 0.15",
|
|
2020
2032
|
"seed-1-6-250615": "0.25 0.05 2",
|
|
@@ -2041,7 +2053,6 @@
|
|
|
2041
2053
|
"seed-oss-36b-instruct": "0.217086 0.217086 0.583895",
|
|
2042
2054
|
"shisa-v2-llama3.3-70b": "0.5 0.25 0.5",
|
|
2043
2055
|
"shisa-v2.1-llama3.3-70b": "0.5 0.25 0.5",
|
|
2044
|
-
"skyfall-31b-v4.2": "0.12 0.06 0.15",
|
|
2045
2056
|
"skyfall-36b-v2": "0.55 0.25 0.8",
|
|
2046
2057
|
"small": "0.0255 0.0025 0.2005",
|
|
2047
2058
|
"solar-mini": "0.15 0.15 0.15",
|
|
@@ -2069,6 +2080,8 @@
|
|
|
2069
2080
|
"step-3.7-flash:thinking": "0.2 0.04 1.15",
|
|
2070
2081
|
"step-5-preview": "1 0.1 2.7",
|
|
2071
2082
|
"summarize": "0.045 0.045 0",
|
|
2083
|
+
"synth-2.5-flash": "0.03 0.03 0.1",
|
|
2084
|
+
"synth-2.5-pro": "0.1 0.1 0.2",
|
|
2072
2085
|
"ternary-bonsai-2-27b": "0.075 0.0375 0.5",
|
|
2073
2086
|
"ternary-bonsai-2-9b": "0.08 0.04 0.13",
|
|
2074
2087
|
"text-embedding-3-large": "0.13 0.13 0",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-claude-style",
|
|
3
3
|
"description": "Claude Code Desktop theme for DeepSeek Harness (dsh) web GUI — visual & interaction overhaul",
|
|
4
|
-
"version": "0.19.
|
|
4
|
+
"version": "0.19.3-dev.48",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/host/index.js",
|
|
7
7
|
"icon": "lib/claude-mark.svg",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|