@kimuson/claude-code-viewer 0.4.4 → 0.4.5
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/dist/main.js +247 -6
- package/dist/main.js.map +4 -4
- package/dist/static/assets/{index-XKo9yk8p.js → index-BHWHZ-91.js} +1 -1
- package/dist/static/assets/{index-hJaFyqiY.js → index-BuR5pLkN.js} +58 -53
- package/dist/static/assets/{index-DutDIkvw.js → index-BwRuqrVH.js} +1 -1
- package/dist/static/assets/{index-DFmNnbaj.js → index-CYLe5Tc7.js} +1 -1
- package/dist/static/assets/{index-yRcA1geA.js → index-D1IPE4nC.js} +3 -3
- package/dist/static/assets/{index-DLA4zb1O.js → index-DovipUdR.js} +1 -1
- package/dist/static/assets/index-sJq6n11H.js +1 -0
- package/dist/static/assets/{label-Dws6Ewzu.js → label-l0et4hNL.js} +6 -6
- package/dist/static/assets/{messages-DLi20Ryh.js → messages-BLhYHIq_.js} +1 -1
- package/dist/static/assets/{messages-H7YsW45d.js → messages-BQx1DYxh.js} +1 -1
- package/dist/static/assets/{messages-ChjmV9GI.js → messages-DZXmj7Ql.js} +1 -1
- package/dist/static/index.html +1 -1
- package/package.json +1 -1
- package/dist/static/assets/index-52rNYQAH.js +0 -1
package/dist/main.js
CHANGED
|
@@ -1181,13 +1181,64 @@ import { Context as Context17, Effect as Effect20, Layer as Layer18 } from "effe
|
|
|
1181
1181
|
|
|
1182
1182
|
// src/server/core/platform/services/UserConfigService.ts
|
|
1183
1183
|
import { Context as Context11, Effect as Effect13, Layer as Layer12, Ref as Ref5 } from "effect";
|
|
1184
|
+
|
|
1185
|
+
// src/lib/i18n/localeDetection.ts
|
|
1186
|
+
var DEFAULT_LOCALE = "en";
|
|
1187
|
+
var normalizeTag = (tag) => {
|
|
1188
|
+
if (!tag) {
|
|
1189
|
+
return void 0;
|
|
1190
|
+
}
|
|
1191
|
+
const normalized = tag.trim().toLowerCase().replaceAll("_", "-");
|
|
1192
|
+
if (normalized.length === 0 || normalized === "*") {
|
|
1193
|
+
return void 0;
|
|
1194
|
+
}
|
|
1195
|
+
if (normalized.startsWith("zh")) {
|
|
1196
|
+
return "zh_CN";
|
|
1197
|
+
}
|
|
1198
|
+
if (normalized.startsWith("ja") || normalized.startsWith("jp")) {
|
|
1199
|
+
return "ja";
|
|
1200
|
+
}
|
|
1201
|
+
if (normalized.startsWith("en")) {
|
|
1202
|
+
return "en";
|
|
1203
|
+
}
|
|
1204
|
+
return void 0;
|
|
1205
|
+
};
|
|
1206
|
+
var detectLocaleFromAcceptLanguage = (header) => {
|
|
1207
|
+
if (!header) {
|
|
1208
|
+
return void 0;
|
|
1209
|
+
}
|
|
1210
|
+
const preferences = header.split(",").map((part, index) => {
|
|
1211
|
+
const [rawTag, ...params] = part.trim().split(";");
|
|
1212
|
+
const qParam = params.map((param) => param.trim()).find((param) => param.startsWith("q="));
|
|
1213
|
+
const quality = qParam ? Number.parseFloat(qParam.slice(2)) : 1;
|
|
1214
|
+
return {
|
|
1215
|
+
tag: rawTag,
|
|
1216
|
+
quality: Number.isNaN(quality) ? 1 : quality,
|
|
1217
|
+
index
|
|
1218
|
+
};
|
|
1219
|
+
}).filter((item) => Boolean(item.tag)).sort((a, b) => {
|
|
1220
|
+
if (b.quality !== a.quality) {
|
|
1221
|
+
return b.quality - a.quality;
|
|
1222
|
+
}
|
|
1223
|
+
return a.index - b.index;
|
|
1224
|
+
});
|
|
1225
|
+
for (const preference of preferences) {
|
|
1226
|
+
const locale = normalizeTag(preference.tag);
|
|
1227
|
+
if (locale) {
|
|
1228
|
+
return locale;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
return void 0;
|
|
1232
|
+
};
|
|
1233
|
+
|
|
1234
|
+
// src/server/core/platform/services/UserConfigService.ts
|
|
1184
1235
|
var LayerImpl10 = Effect13.gen(function* () {
|
|
1185
1236
|
const configRef = yield* Ref5.make({
|
|
1186
1237
|
hideNoUserMessageSession: true,
|
|
1187
1238
|
unifySameTitleSession: false,
|
|
1188
1239
|
enterKeyBehavior: "shift-enter-send",
|
|
1189
1240
|
permissionMode: "default",
|
|
1190
|
-
locale:
|
|
1241
|
+
locale: DEFAULT_LOCALE,
|
|
1191
1242
|
theme: "system"
|
|
1192
1243
|
});
|
|
1193
1244
|
const setUserConfig = (newConfig) => Effect13.gen(function* () {
|
|
@@ -1377,6 +1428,97 @@ var VirtualConversationDatabase = class extends Context12.Tag(
|
|
|
1377
1428
|
import { FileSystem as FileSystem5 } from "@effect/platform";
|
|
1378
1429
|
import { Context as Context13, Effect as Effect15, Layer as Layer14, Ref as Ref7 } from "effect";
|
|
1379
1430
|
|
|
1431
|
+
// src/server/core/session/constants/pricing.ts
|
|
1432
|
+
var MODEL_PRICING = {
|
|
1433
|
+
"claude-3.5-sonnet": {
|
|
1434
|
+
input: 3,
|
|
1435
|
+
output: 15,
|
|
1436
|
+
cache_creation: 3.75,
|
|
1437
|
+
cache_read: 0.3
|
|
1438
|
+
},
|
|
1439
|
+
"claude-3-opus": {
|
|
1440
|
+
input: 15,
|
|
1441
|
+
output: 75,
|
|
1442
|
+
cache_creation: 18.75,
|
|
1443
|
+
cache_read: 1.5
|
|
1444
|
+
},
|
|
1445
|
+
"claude-3-haiku": {
|
|
1446
|
+
input: 0.25,
|
|
1447
|
+
output: 1.25,
|
|
1448
|
+
cache_creation: 0.3,
|
|
1449
|
+
cache_read: 0.03
|
|
1450
|
+
},
|
|
1451
|
+
"claude-instant-1.2": {
|
|
1452
|
+
input: 1.63,
|
|
1453
|
+
output: 5.51,
|
|
1454
|
+
cache_creation: 2.0375,
|
|
1455
|
+
// 1.63 * 1.25
|
|
1456
|
+
cache_read: 0.163
|
|
1457
|
+
// 1.63 * 0.1
|
|
1458
|
+
},
|
|
1459
|
+
"claude-2": {
|
|
1460
|
+
input: 8,
|
|
1461
|
+
output: 24,
|
|
1462
|
+
cache_creation: 10,
|
|
1463
|
+
// 8.0 * 1.25
|
|
1464
|
+
cache_read: 0.8
|
|
1465
|
+
// 8.0 * 0.1
|
|
1466
|
+
}
|
|
1467
|
+
};
|
|
1468
|
+
var DEFAULT_MODEL_PRICING = MODEL_PRICING["claude-3.5-sonnet"];
|
|
1469
|
+
|
|
1470
|
+
// src/server/core/session/functions/calculateSessionCost.ts
|
|
1471
|
+
function normalizeModelName(modelName) {
|
|
1472
|
+
const normalized = modelName.toLowerCase();
|
|
1473
|
+
if (normalized.includes("sonnet-4") || normalized.includes("3-5-sonnet") || normalized.includes("3.5-sonnet")) {
|
|
1474
|
+
return "claude-3.5-sonnet";
|
|
1475
|
+
}
|
|
1476
|
+
if (normalized.includes("3-opus") || normalized.includes("opus-20")) {
|
|
1477
|
+
return "claude-3-opus";
|
|
1478
|
+
}
|
|
1479
|
+
if (normalized.includes("3-haiku") || normalized.includes("haiku-20")) {
|
|
1480
|
+
return "claude-3-haiku";
|
|
1481
|
+
}
|
|
1482
|
+
if (normalized.includes("instant-1.2") || normalized.includes("instant-1")) {
|
|
1483
|
+
return "claude-instant-1.2";
|
|
1484
|
+
}
|
|
1485
|
+
if (normalized.startsWith("claude-2")) {
|
|
1486
|
+
return "claude-2";
|
|
1487
|
+
}
|
|
1488
|
+
return "claude-3.5-sonnet";
|
|
1489
|
+
}
|
|
1490
|
+
function getModelPricing(modelName) {
|
|
1491
|
+
const normalized = normalizeModelName(modelName);
|
|
1492
|
+
return MODEL_PRICING[normalized] ?? DEFAULT_MODEL_PRICING;
|
|
1493
|
+
}
|
|
1494
|
+
function calculateTokenCost(usage, modelName) {
|
|
1495
|
+
const pricing = getModelPricing(modelName);
|
|
1496
|
+
const inputMTok = usage.input_tokens / 1e6;
|
|
1497
|
+
const outputMTok = usage.output_tokens / 1e6;
|
|
1498
|
+
const cacheCreationMTok = (usage.cache_creation_input_tokens ?? 0) / 1e6;
|
|
1499
|
+
const cacheReadMTok = (usage.cache_read_input_tokens ?? 0) / 1e6;
|
|
1500
|
+
const inputTokensUsd = inputMTok * pricing.input;
|
|
1501
|
+
const outputTokensUsd = outputMTok * pricing.output;
|
|
1502
|
+
const cacheCreationUsd = cacheCreationMTok * pricing.cache_creation;
|
|
1503
|
+
const cacheReadUsd = cacheReadMTok * pricing.cache_read;
|
|
1504
|
+
const totalUsd = inputTokensUsd + outputTokensUsd + cacheCreationUsd + cacheReadUsd;
|
|
1505
|
+
return {
|
|
1506
|
+
totalUsd,
|
|
1507
|
+
breakdown: {
|
|
1508
|
+
inputTokensUsd,
|
|
1509
|
+
outputTokensUsd,
|
|
1510
|
+
cacheCreationUsd,
|
|
1511
|
+
cacheReadUsd
|
|
1512
|
+
},
|
|
1513
|
+
tokenUsage: {
|
|
1514
|
+
inputTokens: usage.input_tokens,
|
|
1515
|
+
outputTokens: usage.output_tokens,
|
|
1516
|
+
cacheCreationTokens: usage.cache_creation_input_tokens ?? 0,
|
|
1517
|
+
cacheReadTokens: usage.cache_read_input_tokens ?? 0
|
|
1518
|
+
}
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1380
1522
|
// src/server/core/session/functions/extractFirstUserText.ts
|
|
1381
1523
|
var extractFirstUserText = (conversation) => {
|
|
1382
1524
|
if (conversation.type !== "user") {
|
|
@@ -1463,6 +1605,68 @@ var SessionMetaService = class extends Context13.Tag("SessionMetaService")() {
|
|
|
1463
1605
|
}
|
|
1464
1606
|
return firstUserMessage;
|
|
1465
1607
|
});
|
|
1608
|
+
const aggregateTokenUsageAndCost = (content) => {
|
|
1609
|
+
let totalInputTokens = 0;
|
|
1610
|
+
let totalOutputTokens = 0;
|
|
1611
|
+
let totalCacheCreationTokens = 0;
|
|
1612
|
+
let totalCacheReadTokens = 0;
|
|
1613
|
+
let totalInputTokensUsd = 0;
|
|
1614
|
+
let totalOutputTokensUsd = 0;
|
|
1615
|
+
let totalCacheCreationUsd = 0;
|
|
1616
|
+
let totalCacheReadUsd = 0;
|
|
1617
|
+
let lastModelName = "claude-3.5-sonnet";
|
|
1618
|
+
const conversations = parseJsonl(content);
|
|
1619
|
+
for (const conversation of conversations) {
|
|
1620
|
+
if (conversation.type === "assistant") {
|
|
1621
|
+
const usage = conversation.message.usage;
|
|
1622
|
+
const modelName = conversation.message.model;
|
|
1623
|
+
const messageCost = calculateTokenCost(
|
|
1624
|
+
{
|
|
1625
|
+
input_tokens: usage.input_tokens,
|
|
1626
|
+
output_tokens: usage.output_tokens,
|
|
1627
|
+
cache_creation_input_tokens: usage.cache_creation_input_tokens ?? 0,
|
|
1628
|
+
cache_read_input_tokens: usage.cache_read_input_tokens ?? 0
|
|
1629
|
+
},
|
|
1630
|
+
modelName
|
|
1631
|
+
);
|
|
1632
|
+
totalInputTokens += usage.input_tokens;
|
|
1633
|
+
totalOutputTokens += usage.output_tokens;
|
|
1634
|
+
totalCacheCreationTokens += usage.cache_creation_input_tokens ?? 0;
|
|
1635
|
+
totalCacheReadTokens += usage.cache_read_input_tokens ?? 0;
|
|
1636
|
+
totalInputTokensUsd += messageCost.breakdown.inputTokensUsd;
|
|
1637
|
+
totalOutputTokensUsd += messageCost.breakdown.outputTokensUsd;
|
|
1638
|
+
totalCacheCreationUsd += messageCost.breakdown.cacheCreationUsd;
|
|
1639
|
+
totalCacheReadUsd += messageCost.breakdown.cacheReadUsd;
|
|
1640
|
+
lastModelName = modelName;
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
const totalCost = {
|
|
1644
|
+
totalUsd: totalInputTokensUsd + totalOutputTokensUsd + totalCacheCreationUsd + totalCacheReadUsd,
|
|
1645
|
+
breakdown: {
|
|
1646
|
+
inputTokensUsd: totalInputTokensUsd,
|
|
1647
|
+
outputTokensUsd: totalOutputTokensUsd,
|
|
1648
|
+
cacheCreationUsd: totalCacheCreationUsd,
|
|
1649
|
+
cacheReadUsd: totalCacheReadUsd
|
|
1650
|
+
},
|
|
1651
|
+
tokenUsage: {
|
|
1652
|
+
inputTokens: totalInputTokens,
|
|
1653
|
+
outputTokens: totalOutputTokens,
|
|
1654
|
+
cacheCreationTokens: totalCacheCreationTokens,
|
|
1655
|
+
cacheReadTokens: totalCacheReadTokens
|
|
1656
|
+
}
|
|
1657
|
+
};
|
|
1658
|
+
const aggregatedUsage = {
|
|
1659
|
+
input_tokens: totalInputTokens,
|
|
1660
|
+
output_tokens: totalOutputTokens,
|
|
1661
|
+
cache_creation_input_tokens: totalCacheCreationTokens,
|
|
1662
|
+
cache_read_input_tokens: totalCacheReadTokens
|
|
1663
|
+
};
|
|
1664
|
+
return {
|
|
1665
|
+
totalUsage: aggregatedUsage,
|
|
1666
|
+
totalCost,
|
|
1667
|
+
modelName: lastModelName
|
|
1668
|
+
};
|
|
1669
|
+
};
|
|
1466
1670
|
const getSessionMeta = (projectId, sessionId) => Effect15.gen(function* () {
|
|
1467
1671
|
const metaCache = yield* Ref7.get(sessionMetaCacheRef);
|
|
1468
1672
|
const cached = metaCache.get(sessionId);
|
|
@@ -1476,9 +1680,15 @@ var SessionMetaService = class extends Context13.Tag("SessionMetaService")() {
|
|
|
1476
1680
|
sessionPath,
|
|
1477
1681
|
lines
|
|
1478
1682
|
);
|
|
1683
|
+
const { totalCost } = aggregateTokenUsageAndCost(content);
|
|
1479
1684
|
const sessionMeta = {
|
|
1480
1685
|
messageCount: lines.length,
|
|
1481
|
-
firstUserMessage
|
|
1686
|
+
firstUserMessage,
|
|
1687
|
+
cost: {
|
|
1688
|
+
totalUsd: totalCost.totalUsd,
|
|
1689
|
+
breakdown: totalCost.breakdown,
|
|
1690
|
+
tokenUsage: totalCost.tokenUsage
|
|
1691
|
+
}
|
|
1482
1692
|
};
|
|
1483
1693
|
yield* Ref7.update(sessionMetaCacheRef, (cache) => {
|
|
1484
1694
|
cache.set(sessionId, sessionMeta);
|
|
@@ -1569,7 +1779,22 @@ var LayerImpl11 = Effect16.gen(function* () {
|
|
|
1569
1779
|
jsonlFilePath: `${decodeProjectId(projectId)}/${sessionId}.jsonl`,
|
|
1570
1780
|
meta: {
|
|
1571
1781
|
messageCount: 0,
|
|
1572
|
-
firstUserMessage: null
|
|
1782
|
+
firstUserMessage: null,
|
|
1783
|
+
cost: {
|
|
1784
|
+
totalUsd: 0,
|
|
1785
|
+
breakdown: {
|
|
1786
|
+
inputTokensUsd: 0,
|
|
1787
|
+
outputTokensUsd: 0,
|
|
1788
|
+
cacheCreationUsd: 0,
|
|
1789
|
+
cacheReadUsd: 0
|
|
1790
|
+
},
|
|
1791
|
+
tokenUsage: {
|
|
1792
|
+
inputTokens: 0,
|
|
1793
|
+
outputTokens: 0,
|
|
1794
|
+
cacheCreationTokens: 0,
|
|
1795
|
+
cacheReadTokens: 0
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1573
1798
|
},
|
|
1574
1799
|
conversations: virtualConversation.conversations,
|
|
1575
1800
|
lastModifiedAt: lastConversation !== void 0 ? new Date(lastConversation.timestamp) : /* @__PURE__ */ new Date()
|
|
@@ -1670,7 +1895,22 @@ var LayerImpl11 = Effect16.gen(function* () {
|
|
|
1670
1895
|
lastModifiedAt: last !== void 0 ? new Date(last.timestamp) : /* @__PURE__ */ new Date(),
|
|
1671
1896
|
meta: {
|
|
1672
1897
|
messageCount: conversations.length,
|
|
1673
|
-
firstUserMessage: firstUserText ? parseUserMessage(firstUserText) : null
|
|
1898
|
+
firstUserMessage: firstUserText ? parseUserMessage(firstUserText) : null,
|
|
1899
|
+
cost: {
|
|
1900
|
+
totalUsd: 0,
|
|
1901
|
+
breakdown: {
|
|
1902
|
+
inputTokensUsd: 0,
|
|
1903
|
+
outputTokensUsd: 0,
|
|
1904
|
+
cacheCreationUsd: 0,
|
|
1905
|
+
cacheReadUsd: 0
|
|
1906
|
+
},
|
|
1907
|
+
tokenUsage: {
|
|
1908
|
+
inputTokens: 0,
|
|
1909
|
+
outputTokens: 0,
|
|
1910
|
+
cacheCreationTokens: 0,
|
|
1911
|
+
cacheReadTokens: 0
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1674
1914
|
}
|
|
1675
1915
|
};
|
|
1676
1916
|
}).sort((a, b) => {
|
|
@@ -4876,7 +5116,7 @@ import { z as z28 } from "zod";
|
|
|
4876
5116
|
// package.json
|
|
4877
5117
|
var package_default = {
|
|
4878
5118
|
name: "@kimuson/claude-code-viewer",
|
|
4879
|
-
version: "0.4.
|
|
5119
|
+
version: "0.4.4",
|
|
4880
5120
|
type: "module",
|
|
4881
5121
|
license: "MIT",
|
|
4882
5122
|
repository: {
|
|
@@ -5169,6 +5409,7 @@ var configMiddleware = createMiddleware(
|
|
|
5169
5409
|
const cookie = getCookie(c, "ccv-config");
|
|
5170
5410
|
const parsed = parseUserConfig(cookie);
|
|
5171
5411
|
if (cookie === void 0) {
|
|
5412
|
+
const preferredLocale = detectLocaleFromAcceptLanguage(c.req.header("accept-language")) ?? DEFAULT_LOCALE;
|
|
5172
5413
|
setCookie(
|
|
5173
5414
|
c,
|
|
5174
5415
|
"ccv-config",
|
|
@@ -5177,7 +5418,7 @@ var configMiddleware = createMiddleware(
|
|
|
5177
5418
|
unifySameTitleSession: true,
|
|
5178
5419
|
enterKeyBehavior: "shift-enter-send",
|
|
5179
5420
|
permissionMode: "default",
|
|
5180
|
-
locale:
|
|
5421
|
+
locale: preferredLocale,
|
|
5181
5422
|
theme: "system"
|
|
5182
5423
|
})
|
|
5183
5424
|
);
|