@morlay/ui-conversation-message-actions 0.1.4 → 0.1.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/client.cjs +1216 -2337
- package/dist/{rolldown-runtime-BMI-E3GI.mjs → rolldown-runtime-Dr7-SnC6.mjs} +2 -1
- package/dist/testing.mjs +1 -1
- package/package.json +4 -4
- package/src/client/chat-node/MessageItem.tsx +36 -17
- package/src/client/index.ts +1 -6
- package/src/client/chat-node/MessageIconActions.styles.ts +0 -76
- package/src/client/chat-node/MessageIconActions.tsx +0 -166
- package/src/client/chat-node/MessageItem.styles.ts +0 -248
- package/src/client/chat-node/message-chrome.ts +0 -44
- package/src/client/chat-node/use-calendar-day.ts +0 -19
- package/src/client/composer-stats/StatsPills.styles.ts +0 -57
- package/src/client/composer-stats/StatsPills.tsx +0 -362
- package/src/client/composer-stats/register.ts +0 -17
- package/src/client/composer-stats/stat-dialog.styles.ts +0 -70
- package/src/client/composer-stats/stat-dialog.ts +0 -52
- package/src/client/composer-stats/token-format.ts +0 -84
- package/src/client/composer-stats/turn-reading.ts +0 -35
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
// Token 展示口径:`formatCacheHitPercent` 的越界分支是**主动修的缺陷**(上游只在未命中侧为 0 时返回 "100",
|
|
2
|
-
// cacheRead 超出 prompt 时展开循环的缩放间隙恒为负 → 同步死循环冻结主线程),这里保持修好的口径。
|
|
3
|
-
import type { ChatViewSlotProps } from "@deepseek-ai/dsh-client-ui-chat/client";
|
|
4
|
-
|
|
5
|
-
export function formatTokens(value: number, t: ChatViewSlotProps["t"]): string {
|
|
6
|
-
const scaled = (candidate: number): string =>
|
|
7
|
-
candidate >= 100 ? String(Math.round(candidate)) : String(Math.round(candidate * 10) / 10);
|
|
8
|
-
if (value < 1_000) return String(value);
|
|
9
|
-
if (value < 1_000_000) return t("number.thousand", { value: scaled(value / 1_000) });
|
|
10
|
-
return t("number.million", { value: scaled(value / 1_000_000) });
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function formatExactTokens(value: number, t: ChatViewSlotProps["t"]): string {
|
|
14
|
-
const digits = String(value);
|
|
15
|
-
const groups: string[] = [];
|
|
16
|
-
for (let end = digits.length; end > 0; end -= 3) {
|
|
17
|
-
groups.unshift(digits.slice(Math.max(0, end - 3), end));
|
|
18
|
-
}
|
|
19
|
-
return groups.join(t("number.groupSeparator"));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function roundedPercentUnits(
|
|
23
|
-
cacheReadTokens: number,
|
|
24
|
-
denominator: number,
|
|
25
|
-
decimalPlaces: 0 | 1,
|
|
26
|
-
): number {
|
|
27
|
-
const unitsPerPercent = decimalPlaces === 0 ? 1 : 10;
|
|
28
|
-
const scale = unitsPerPercent * 100;
|
|
29
|
-
const doubledScale = scale * 2;
|
|
30
|
-
const denominatorQuotient = Math.floor(denominator / doubledScale);
|
|
31
|
-
const denominatorRemainder = denominator % doubledScale;
|
|
32
|
-
let lower = 0;
|
|
33
|
-
let upper = scale;
|
|
34
|
-
while (lower < upper) {
|
|
35
|
-
const candidate = Math.floor((lower + upper + 1) / 2);
|
|
36
|
-
const factor = candidate * 2 - 1;
|
|
37
|
-
const threshold =
|
|
38
|
-
factor * denominatorQuotient + Math.ceil((factor * denominatorRemainder) / doubledScale);
|
|
39
|
-
if (cacheReadTokens >= threshold) lower = candidate;
|
|
40
|
-
else upper = candidate - 1;
|
|
41
|
-
}
|
|
42
|
-
return lower;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function displayPercentUnits(units: number, decimalPlaces: 0 | 1): string {
|
|
46
|
-
if (decimalPlaces === 0) return String(units);
|
|
47
|
-
const whole = Math.floor(units / 10);
|
|
48
|
-
const tenths = units % 10;
|
|
49
|
-
return tenths === 0 ? String(whole) : `${whole}.${tenths}`;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function formatCacheHitPercent(
|
|
53
|
-
cacheReadTokens: number,
|
|
54
|
-
promptTokens: number,
|
|
55
|
-
decimalPlaces: 0 | 1 = 0,
|
|
56
|
-
): string | null {
|
|
57
|
-
if (promptTokens === 0) return null;
|
|
58
|
-
const missedInputTokens = promptTokens - cacheReadTokens;
|
|
59
|
-
// 未命中侧为 0,或为负(cacheRead 超出 prompt 的越界输入)时都按全命中返回。
|
|
60
|
-
if (missedInputTokens <= 0) return "100";
|
|
61
|
-
|
|
62
|
-
const roundedUnits = roundedPercentUnits(cacheReadTokens, promptTokens, decimalPlaces);
|
|
63
|
-
const fullHitUnits = decimalPlaces === 0 ? 100 : 1_000;
|
|
64
|
-
if (roundedUnits < fullHitUnits) return displayPercentUnits(roundedUnits, decimalPlaces);
|
|
65
|
-
|
|
66
|
-
let distinguishingPlaces = 1;
|
|
67
|
-
let scaledDoubleGap = missedInputTokens * 200;
|
|
68
|
-
const denominatorTens = Math.floor(promptTokens / 10);
|
|
69
|
-
while (scaledDoubleGap <= denominatorTens) {
|
|
70
|
-
scaledDoubleGap *= 10;
|
|
71
|
-
distinguishingPlaces += 1;
|
|
72
|
-
}
|
|
73
|
-
const denominatorOnes = promptTokens % 10;
|
|
74
|
-
let roundedLoss = 5;
|
|
75
|
-
for (let loss = 1; loss < 5; loss += 1) {
|
|
76
|
-
const factor = loss * 2 + 1;
|
|
77
|
-
const threshold = factor * denominatorTens + Math.floor((factor * denominatorOnes) / 10);
|
|
78
|
-
if (scaledDoubleGap <= threshold) {
|
|
79
|
-
roundedLoss = loss;
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return `99.${"9".repeat(distinguishingPlaces - 1)}${10 - roundedLoss}`;
|
|
84
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// 窗口折叠(无 `sessionStats` 投影时的兜底)读一条 assistant 步的时序 / 用量。
|
|
2
|
-
// 从上游 ui-chat 的 `contract/turn-metrics.ts` 取出统计行真正用到的那一半,
|
|
3
|
-
// 只服务 composer 统计行。
|
|
4
|
-
import type { AssistantMessageNode } from "@deepseek-ai/dsh-client-ui-chat/client";
|
|
5
|
-
|
|
6
|
-
export interface StepReading {
|
|
7
|
-
ttftMs: number | null;
|
|
8
|
-
|
|
9
|
-
decodeMs: number | null;
|
|
10
|
-
|
|
11
|
-
outputTokens: number | null;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface UsageLike {
|
|
15
|
-
outputTokens?: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function usageOutputTokens(usage: unknown): number | null {
|
|
19
|
-
if (typeof usage !== "object" || usage === null) return null;
|
|
20
|
-
const value = (usage as UsageLike).outputTokens;
|
|
21
|
-
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function assistantStepReading(node: AssistantMessageNode): StepReading {
|
|
25
|
-
const timing = node.timing;
|
|
26
|
-
const ttftMs =
|
|
27
|
-
timing !== undefined && timing.stepStartTime !== null && timing.firstTokenTime !== null
|
|
28
|
-
? Math.max(0, timing.firstTokenTime - timing.stepStartTime)
|
|
29
|
-
: null;
|
|
30
|
-
const decodeMs =
|
|
31
|
-
timing !== undefined && timing.firstTokenTime !== null
|
|
32
|
-
? Math.max(0, timing.completedTime - timing.firstTokenTime)
|
|
33
|
-
: null;
|
|
34
|
-
return { ttftMs, decodeMs, outputTokens: usageOutputTokens(node.usage) };
|
|
35
|
-
}
|