@memori.ai/memori-react 8.29.0 → 8.30.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/CHANGELOG.md +30 -0
- package/README.md +1 -1
- package/dist/components/Chat/Chat.css +110 -9
- package/dist/components/Chat/Chat.d.ts +1 -0
- package/dist/components/Chat/Chat.js +72 -5
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/ChatBubble/ChatBubble.d.ts +1 -0
- package/dist/components/ChatBubble/ChatBubble.js +6 -6
- package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
- package/dist/components/ChatInputs/ChatInputs.js +2 -11
- package/dist/components/ChatInputs/ChatInputs.js.map +1 -1
- package/dist/components/DrawerFooter/DrawerFooter.css +0 -1
- package/dist/components/MemoriWidget/MemoriWidget.d.ts +2 -1
- package/dist/components/MemoriWidget/MemoriWidget.js +13 -3
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/MicrophoneButton/MicrophoneButton.css +4 -14
- package/dist/components/MicrophoneButton/MicrophoneButton.js +1 -1
- package/dist/components/MicrophoneButton/MicrophoneButton.js.map +1 -1
- package/dist/components/StartPanel/StartPanel.js +1 -1
- package/dist/components/StartPanel/StartPanel.js.map +1 -1
- package/dist/components/UploadButton/UploadButton.js +8 -14
- package/dist/components/UploadButton/UploadButton.js.map +1 -1
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.d.ts +0 -1
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +1 -20
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
- package/dist/components/layouts/fullpage.css +3 -1
- package/dist/components/layouts/website-assistant.css +1 -0
- package/dist/components/ui/Tooltip.css +9 -1
- package/dist/components/ui/Tooltip.js +80 -4
- package/dist/components/ui/Tooltip.js.map +1 -1
- package/dist/helpers/constants.d.ts +1 -2
- package/dist/helpers/constants.js +2 -3
- package/dist/helpers/constants.js.map +1 -1
- package/dist/helpers/llmUsage.d.ts +60 -0
- package/dist/helpers/llmUsage.js +223 -0
- package/dist/helpers/llmUsage.js.map +1 -0
- package/dist/helpers/message.d.ts +1 -0
- package/dist/helpers/message.js +3 -1
- package/dist/helpers/message.js.map +1 -1
- package/dist/helpers/userMessage.d.ts +2 -0
- package/dist/helpers/userMessage.js +23 -0
- package/dist/helpers/userMessage.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/locales/de.json +22 -0
- package/dist/locales/en.json +22 -0
- package/dist/locales/es.json +22 -0
- package/dist/locales/fr.json +22 -0
- package/dist/locales/it.json +22 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/esm/components/Chat/Chat.css +110 -9
- package/esm/components/Chat/Chat.d.ts +1 -0
- package/esm/components/Chat/Chat.js +74 -7
- package/esm/components/Chat/Chat.js.map +1 -1
- package/esm/components/ChatBubble/ChatBubble.d.ts +1 -0
- package/esm/components/ChatBubble/ChatBubble.js +7 -7
- package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
- package/esm/components/ChatInputs/ChatInputs.js +2 -11
- package/esm/components/ChatInputs/ChatInputs.js.map +1 -1
- package/esm/components/DrawerFooter/DrawerFooter.css +0 -1
- package/esm/components/MemoriWidget/MemoriWidget.d.ts +2 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +13 -3
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/MicrophoneButton/MicrophoneButton.css +4 -14
- package/esm/components/MicrophoneButton/MicrophoneButton.js +1 -1
- package/esm/components/MicrophoneButton/MicrophoneButton.js.map +1 -1
- package/esm/components/StartPanel/StartPanel.js +1 -1
- package/esm/components/StartPanel/StartPanel.js.map +1 -1
- package/esm/components/UploadButton/UploadButton.js +8 -14
- package/esm/components/UploadButton/UploadButton.js.map +1 -1
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.d.ts +0 -1
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +1 -20
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
- package/esm/components/layouts/fullpage.css +3 -1
- package/esm/components/layouts/website-assistant.css +1 -0
- package/esm/components/ui/Tooltip.css +9 -1
- package/esm/components/ui/Tooltip.js +81 -5
- package/esm/components/ui/Tooltip.js.map +1 -1
- package/esm/helpers/constants.d.ts +1 -2
- package/esm/helpers/constants.js +1 -2
- package/esm/helpers/constants.js.map +1 -1
- package/esm/helpers/llmUsage.d.ts +60 -0
- package/esm/helpers/llmUsage.js +212 -0
- package/esm/helpers/llmUsage.js.map +1 -0
- package/esm/helpers/message.d.ts +1 -0
- package/esm/helpers/message.js +1 -0
- package/esm/helpers/message.js.map +1 -1
- package/esm/helpers/userMessage.d.ts +2 -0
- package/esm/helpers/userMessage.js +18 -0
- package/esm/helpers/userMessage.js.map +1 -0
- package/esm/index.d.ts +1 -0
- package/esm/index.js +3 -1
- package/esm/index.js.map +1 -1
- package/esm/locales/de.json +22 -0
- package/esm/locales/en.json +22 -0
- package/esm/locales/es.json +22 -0
- package/esm/locales/fr.json +22 -0
- package/esm/locales/it.json +22 -0
- package/esm/version.d.ts +1 -1
- package/esm/version.js +1 -1
- package/package.json +1 -1
- package/src/components/BlockedMemoriBadge/__snapshots__/BlockedMemoriBadge.test.tsx.snap +0 -29
- package/src/components/Chat/Chat.css +110 -9
- package/src/components/Chat/Chat.stories.tsx +42 -0
- package/src/components/Chat/Chat.test.tsx +47 -0
- package/src/components/Chat/Chat.tsx +238 -5
- package/src/components/Chat/__snapshots__/Chat.test.tsx.snap +745 -0
- package/src/components/ChatBubble/ChatBubble.tsx +20 -7
- package/src/components/ChatBubble/__snapshots__/ChatBubble.test.tsx.snap +0 -20
- package/src/components/ChatInputs/ChatInputs.tsx +4 -15
- package/src/components/CompletionProviderStatus/__snapshots__/CompletionProviderStatus.test.tsx.snap +0 -54
- package/src/components/FeedbackButtons/__snapshots__/FeedbackButtons.test.tsx.snap +0 -5
- package/src/components/MemoriWidget/MemoriWidget.tsx +20 -2
- package/src/components/MicrophoneButton/MicrophoneButton.css +4 -14
- package/src/components/MicrophoneButton/MicrophoneButton.tsx +0 -1
- package/src/components/StartPanel/StartPanel.tsx +1 -1
- package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +11 -368
- package/src/components/UploadButton/UploadButton.stories.tsx +3 -3
- package/src/components/UploadButton/UploadButton.tsx +8 -23
- package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +1 -27
- package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +1 -30
- package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +2 -60
- package/src/components/layouts/__snapshots__/HiddenChat.test.tsx.snap +1 -30
- package/src/components/layouts/__snapshots__/Totem.test.tsx.snap +1 -30
- package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +1 -30
- package/src/components/layouts/website-assistant.css +1 -0
- package/src/components/ui/Tooltip.css +9 -1
- package/src/components/ui/Tooltip.tsx +133 -17
- package/src/components/ui/__snapshots__/Tooltip.test.tsx.snap +5 -55
- package/src/helpers/constants.ts +1 -2
- package/src/helpers/llmUsage.ts +328 -0
- package/src/helpers/message.ts +3 -0
- package/src/index.stories.tsx +2 -3
- package/src/index.tsx +5 -1
- package/src/locales/de.json +22 -0
- package/src/locales/en.json +22 -0
- package/src/locales/es.json +22 -0
- package/src/locales/fr.json +22 -0
- package/src/locales/it.json +22 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
export interface LlmUsageOnLine {
|
|
2
|
+
provider?: string;
|
|
3
|
+
model?: string;
|
|
4
|
+
totalInputTokens?: number;
|
|
5
|
+
inputCacheReadTokens?: number;
|
|
6
|
+
inputCacheWriteTokens?: number;
|
|
7
|
+
outputTokens?: number;
|
|
8
|
+
durationMs?: number;
|
|
9
|
+
energyImpact?: {
|
|
10
|
+
energy?: number | { source?: string; parsedValue?: number };
|
|
11
|
+
energyUnit?: string;
|
|
12
|
+
gwp?: number | { source?: string; parsedValue?: number };
|
|
13
|
+
gwpUnit?: string;
|
|
14
|
+
wcf?: number | { source?: string; parsedValue?: number };
|
|
15
|
+
wcfUnit?: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type UsageBadgeType = 'llm' | 'energy' | 'co2' | 'water';
|
|
20
|
+
type NumericMetric = number | { source?: string; parsedValue?: number };
|
|
21
|
+
type ImpactMetricType = 'energy' | 'co2' | 'water';
|
|
22
|
+
type TranslateFn = (key: string, options?: { [key: string]: unknown }) => string;
|
|
23
|
+
|
|
24
|
+
export interface LlmUsageLabels {
|
|
25
|
+
llm: string;
|
|
26
|
+
model: string;
|
|
27
|
+
provider: string;
|
|
28
|
+
tokens: string;
|
|
29
|
+
input: string;
|
|
30
|
+
output: string;
|
|
31
|
+
cacheRead: string;
|
|
32
|
+
cacheWrite: string;
|
|
33
|
+
duration: string;
|
|
34
|
+
energy: string;
|
|
35
|
+
co2: string;
|
|
36
|
+
water: string;
|
|
37
|
+
usageBadgesHint: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const BADGE_EMOJI: Record<UsageBadgeType, string> = {
|
|
41
|
+
llm: '🤖',
|
|
42
|
+
energy: '⚡',
|
|
43
|
+
co2: '🌍',
|
|
44
|
+
water: '💧',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const escapeHtml = (value: string): string =>
|
|
48
|
+
value
|
|
49
|
+
.replaceAll('&', '&')
|
|
50
|
+
.replaceAll('<', '<')
|
|
51
|
+
.replaceAll('>', '>')
|
|
52
|
+
.replaceAll('"', '"')
|
|
53
|
+
.replaceAll("'", ''');
|
|
54
|
+
|
|
55
|
+
export const getMetricValue = (metric?: NumericMetric): number | undefined => {
|
|
56
|
+
if (typeof metric === 'number' && Number.isFinite(metric)) return metric;
|
|
57
|
+
if (!metric || typeof metric !== 'object') return undefined;
|
|
58
|
+
if (
|
|
59
|
+
typeof metric.parsedValue === 'number' &&
|
|
60
|
+
Number.isFinite(metric.parsedValue)
|
|
61
|
+
) {
|
|
62
|
+
return metric.parsedValue;
|
|
63
|
+
}
|
|
64
|
+
if (typeof metric.source === 'string') {
|
|
65
|
+
const parsed = Number(metric.source);
|
|
66
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const formatMetricValue = (value: number, locale = 'it-IT'): string => {
|
|
72
|
+
if (!Number.isFinite(value)) return '—';
|
|
73
|
+
if (value === 0) return '0';
|
|
74
|
+
|
|
75
|
+
const absValue = Math.abs(value);
|
|
76
|
+
return new Intl.NumberFormat(locale, {
|
|
77
|
+
minimumFractionDigits: 0,
|
|
78
|
+
maximumFractionDigits: absValue >= 1 ? 3 : 4,
|
|
79
|
+
}).format(value);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const formatIntegerValue = (value: number, locale = 'it-IT'): string => {
|
|
83
|
+
if (!Number.isFinite(value)) return '0';
|
|
84
|
+
return new Intl.NumberFormat(locale, { maximumFractionDigits: 0 }).format(
|
|
85
|
+
value,
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const formatDuration = (durationMs?: number, locale = 'it-IT'): string => {
|
|
90
|
+
if (typeof durationMs !== 'number' || !Number.isFinite(durationMs)) {
|
|
91
|
+
return '—';
|
|
92
|
+
}
|
|
93
|
+
if (durationMs < 1000) return `${formatIntegerValue(durationMs, locale)} ms`;
|
|
94
|
+
return `${formatMetricValue(durationMs / 1000, locale)} s`;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const floorToSingleDecimal = (value: number): number =>
|
|
98
|
+
Math.floor(value * 10) / 10;
|
|
99
|
+
|
|
100
|
+
const formatComparisonNumber = (value: number, locale = 'it-IT'): string =>
|
|
101
|
+
new Intl.NumberFormat(locale, {
|
|
102
|
+
minimumFractionDigits: 1,
|
|
103
|
+
maximumFractionDigits: 1,
|
|
104
|
+
}).format(floorToSingleDecimal(value));
|
|
105
|
+
|
|
106
|
+
const formatReadableDuration = (seconds: number, locale = 'it-IT'): string => {
|
|
107
|
+
if (!Number.isFinite(seconds) || seconds <= 0) return '0 s';
|
|
108
|
+
if (seconds < 60) return `${formatComparisonNumber(seconds, locale)} s`;
|
|
109
|
+
|
|
110
|
+
const minutes = seconds / 60;
|
|
111
|
+
if (minutes < 60) return `${formatComparisonNumber(minutes, locale)} min`;
|
|
112
|
+
|
|
113
|
+
return `${formatComparisonNumber(minutes / 60, locale)} h`;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const formatReadableDistance = (meters: number, locale = 'it-IT'): string => {
|
|
117
|
+
if (!Number.isFinite(meters) || meters <= 0) return '0 m';
|
|
118
|
+
if (meters < 1000) return `${formatComparisonNumber(meters, locale)} m`;
|
|
119
|
+
return `${formatComparisonNumber(meters / 1000, locale)} km`;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const getApiUnitToBaseFactor = (
|
|
123
|
+
unitFromApi: string | undefined,
|
|
124
|
+
metricType: ImpactMetricType,
|
|
125
|
+
): number => {
|
|
126
|
+
const u = (unitFromApi ?? '').trim().toLowerCase();
|
|
127
|
+
if (metricType === 'energy') {
|
|
128
|
+
if (u === 'kwh') return 1;
|
|
129
|
+
if (u === 'wh') return 0.001;
|
|
130
|
+
if (u === 'mwh') return 0.000001;
|
|
131
|
+
return 1;
|
|
132
|
+
}
|
|
133
|
+
if (metricType === 'co2') {
|
|
134
|
+
if (u === 'kg' || u === 'kgco2eq') return 1;
|
|
135
|
+
if (u === 'g') return 0.001;
|
|
136
|
+
if (u === 'mg') return 0.000001;
|
|
137
|
+
return 1;
|
|
138
|
+
}
|
|
139
|
+
if (u === 'l') return 1;
|
|
140
|
+
if (u === 'ml') return 0.001;
|
|
141
|
+
if (u === 'μl' || u === 'ul') return 0.000001;
|
|
142
|
+
return 1;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export const formatImpactInReadableUnit = (
|
|
146
|
+
value: number,
|
|
147
|
+
metricType: ImpactMetricType,
|
|
148
|
+
locale = 'it-IT',
|
|
149
|
+
): string => {
|
|
150
|
+
const absValue = Math.abs(value);
|
|
151
|
+
|
|
152
|
+
if (metricType === 'energy') {
|
|
153
|
+
if (absValue >= 1) return `${formatMetricValue(value, locale)} kWh`;
|
|
154
|
+
const wattHours = value * 1000;
|
|
155
|
+
if (Math.abs(wattHours) >= 1) return `${formatMetricValue(wattHours, locale)} Wh`;
|
|
156
|
+
return `${formatMetricValue(wattHours * 1000, locale)} mWh`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (metricType === 'co2') {
|
|
160
|
+
if (absValue >= 1) return `${formatMetricValue(value, locale)} kg`;
|
|
161
|
+
const grams = value * 1000;
|
|
162
|
+
if (Math.abs(grams) >= 1) return `${formatMetricValue(grams, locale)} g`;
|
|
163
|
+
return `${formatMetricValue(grams * 1000, locale)} mg`;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (absValue >= 1) return `${formatMetricValue(value, locale)} L`;
|
|
167
|
+
const milliliters = value * 1000;
|
|
168
|
+
if (Math.abs(milliliters) >= 1) return `${formatMetricValue(milliliters, locale)} mL`;
|
|
169
|
+
return `${formatMetricValue(milliliters * 1000, locale)} μL`;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export const formatImpactWithApiUnit = (
|
|
173
|
+
value: number,
|
|
174
|
+
unitFromApi: string | undefined,
|
|
175
|
+
fallbackUnit: string,
|
|
176
|
+
metricType: ImpactMetricType,
|
|
177
|
+
locale = 'it-IT',
|
|
178
|
+
): string => {
|
|
179
|
+
const factor = getApiUnitToBaseFactor(
|
|
180
|
+
unitFromApi ?? fallbackUnit,
|
|
181
|
+
metricType,
|
|
182
|
+
);
|
|
183
|
+
const baseValue = value * factor;
|
|
184
|
+
return formatImpactInReadableUnit(baseValue, metricType, locale);
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export const getImpactComparison = (
|
|
188
|
+
value: number,
|
|
189
|
+
metricType: ImpactMetricType,
|
|
190
|
+
locale = 'it-IT',
|
|
191
|
+
t: TranslateFn,
|
|
192
|
+
): string => {
|
|
193
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
194
|
+
return t('chatLogs.impactComparisonUnavailable');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (metricType === 'energy') {
|
|
198
|
+
const ledSeconds = (value * 1000 * 3600) / 10;
|
|
199
|
+
return t('chatLogs.impactComparisonEnergy', {
|
|
200
|
+
duration: formatReadableDuration(ledSeconds, locale),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (metricType === 'co2') {
|
|
205
|
+
const averageCarMeters = (value / 0.12) * 1000;
|
|
206
|
+
return t('chatLogs.impactComparisonCo2', {
|
|
207
|
+
distance: formatReadableDistance(averageCarMeters, locale),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const drops = (value * 1000) / 0.05;
|
|
212
|
+
return t('chatLogs.impactComparisonWater', {
|
|
213
|
+
count: formatComparisonNumber(drops, locale),
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const buildUsageBadgeHtml = ({
|
|
218
|
+
badgeType,
|
|
219
|
+
badgeClassName,
|
|
220
|
+
label,
|
|
221
|
+
value,
|
|
222
|
+
lineIndex,
|
|
223
|
+
emoji,
|
|
224
|
+
}: {
|
|
225
|
+
badgeType: UsageBadgeType;
|
|
226
|
+
badgeClassName: string;
|
|
227
|
+
label: string;
|
|
228
|
+
value?: string;
|
|
229
|
+
lineIndex: number;
|
|
230
|
+
emoji: string;
|
|
231
|
+
}): string => {
|
|
232
|
+
const escapedLabel = escapeHtml(label);
|
|
233
|
+
const valueHtml = value
|
|
234
|
+
? `<span class="memori-chat--usage-badge-value">${value}</span>`
|
|
235
|
+
: '';
|
|
236
|
+
const content =
|
|
237
|
+
valueHtml ||
|
|
238
|
+
`<span class="memori-chat--usage-badge-label">${escapedLabel}</span>`;
|
|
239
|
+
|
|
240
|
+
return `<button type="button" class="memori-chat--usage-badge ${badgeClassName}" data-llm-badge-type="${badgeType}" data-line-index="${lineIndex}" aria-label="${escapedLabel}">${emoji} ${content}</button>`;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
export const buildLlmUsageHtml = (
|
|
244
|
+
usage: LlmUsageOnLine,
|
|
245
|
+
labels: LlmUsageLabels,
|
|
246
|
+
lineIndex: number,
|
|
247
|
+
locale = 'it-IT',
|
|
248
|
+
): string => {
|
|
249
|
+
const badges = [
|
|
250
|
+
buildUsageBadgeHtml({
|
|
251
|
+
badgeType: 'llm',
|
|
252
|
+
badgeClassName: 'memori-chat--usage-badge-llm',
|
|
253
|
+
label: labels.llm,
|
|
254
|
+
lineIndex,
|
|
255
|
+
emoji: BADGE_EMOJI.llm,
|
|
256
|
+
}),
|
|
257
|
+
];
|
|
258
|
+
|
|
259
|
+
const energy = getMetricValue(usage.energyImpact?.energy);
|
|
260
|
+
const gwp = getMetricValue(usage.energyImpact?.gwp);
|
|
261
|
+
const wcf = getMetricValue(usage.energyImpact?.wcf);
|
|
262
|
+
|
|
263
|
+
if (typeof energy === 'number') {
|
|
264
|
+
const energyFormatted = formatImpactWithApiUnit(
|
|
265
|
+
energy,
|
|
266
|
+
usage.energyImpact?.energyUnit,
|
|
267
|
+
'kWh',
|
|
268
|
+
'energy',
|
|
269
|
+
locale,
|
|
270
|
+
);
|
|
271
|
+
badges.push(
|
|
272
|
+
buildUsageBadgeHtml({
|
|
273
|
+
badgeType: 'energy',
|
|
274
|
+
badgeClassName: 'memori-chat--usage-badge-energy',
|
|
275
|
+
label: `${labels.energy} ${energyFormatted}`,
|
|
276
|
+
value: escapeHtml(energyFormatted),
|
|
277
|
+
lineIndex,
|
|
278
|
+
emoji: BADGE_EMOJI.energy,
|
|
279
|
+
}),
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (typeof gwp === 'number') {
|
|
284
|
+
const co2Formatted = formatImpactWithApiUnit(
|
|
285
|
+
gwp,
|
|
286
|
+
usage.energyImpact?.gwpUnit,
|
|
287
|
+
'kgCO2eq',
|
|
288
|
+
'co2',
|
|
289
|
+
locale,
|
|
290
|
+
);
|
|
291
|
+
badges.push(
|
|
292
|
+
buildUsageBadgeHtml({
|
|
293
|
+
badgeType: 'co2',
|
|
294
|
+
badgeClassName: 'memori-chat--usage-badge-co2',
|
|
295
|
+
label: `${labels.co2} ${co2Formatted}`,
|
|
296
|
+
value: escapeHtml(co2Formatted),
|
|
297
|
+
lineIndex,
|
|
298
|
+
emoji: BADGE_EMOJI.co2,
|
|
299
|
+
}),
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (typeof wcf === 'number') {
|
|
304
|
+
const waterFormatted = formatImpactWithApiUnit(
|
|
305
|
+
wcf,
|
|
306
|
+
usage.energyImpact?.wcfUnit,
|
|
307
|
+
'L',
|
|
308
|
+
'water',
|
|
309
|
+
locale,
|
|
310
|
+
);
|
|
311
|
+
badges.push(
|
|
312
|
+
buildUsageBadgeHtml({
|
|
313
|
+
badgeType: 'water',
|
|
314
|
+
badgeClassName: 'memori-chat--usage-badge-water',
|
|
315
|
+
label: `${labels.water} ${waterFormatted}`,
|
|
316
|
+
value: escapeHtml(waterFormatted),
|
|
317
|
+
lineIndex,
|
|
318
|
+
emoji: BADGE_EMOJI.water,
|
|
319
|
+
}),
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return `<div class="memori-chat--llm-usage" data-llm-usage><hr class="memori-chat--llm-usage-hr" /><p class="memori-chat--llm-usage-hint">${escapeHtml(
|
|
324
|
+
labels.usageBadgesHint,
|
|
325
|
+
)}</p><div class="memori-chat--llm-usage-badges">${badges.join(
|
|
326
|
+
'',
|
|
327
|
+
)}</div></div>`;
|
|
328
|
+
};
|
package/src/helpers/message.ts
CHANGED
package/src/index.stories.tsx
CHANGED
|
@@ -86,8 +86,8 @@ WithChatHistory.args = {
|
|
|
86
86
|
showChatHistory: true,
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
-
export const
|
|
90
|
-
|
|
89
|
+
export const WithUploadNoTotalPayloadLimit = Template.bind({});
|
|
90
|
+
WithUploadNoTotalPayloadLimit.args = {
|
|
91
91
|
ownerUserName: 'nzambello',
|
|
92
92
|
memoriName: 'Nicola',
|
|
93
93
|
tenantID: 'www.aisuru.com',
|
|
@@ -98,7 +98,6 @@ WithUploadWithMaxTotalMessagePayload.args = {
|
|
|
98
98
|
spokenLang: 'IT',
|
|
99
99
|
enableAudio: true,
|
|
100
100
|
showUpload: true,
|
|
101
|
-
maxTotalMessagePayload: 300000,
|
|
102
101
|
};
|
|
103
102
|
|
|
104
103
|
export const WithMaxTextareaCharacters = Template.bind({});
|
package/src/index.tsx
CHANGED
|
@@ -44,6 +44,7 @@ export interface Props {
|
|
|
44
44
|
showInputs?: boolean;
|
|
45
45
|
showDates?: boolean;
|
|
46
46
|
showContextPerLine?: boolean;
|
|
47
|
+
showMessageConsumption?: boolean;
|
|
47
48
|
showSettings?: boolean;
|
|
48
49
|
__WEBCOMPONENT__?: boolean;
|
|
49
50
|
showClear?: boolean;
|
|
@@ -77,7 +78,7 @@ export interface Props {
|
|
|
77
78
|
useMathFormatting?: boolean;
|
|
78
79
|
autoStart?: boolean;
|
|
79
80
|
applyVarsToRoot?: boolean;
|
|
80
|
-
/**
|
|
81
|
+
/** Max per-document content length (character count). Kept name for backward compatibility. Default: 300000. */
|
|
81
82
|
maxTotalMessagePayload?: number;
|
|
82
83
|
/** Max characters allowed in the chat textarea. When set, shows a counter (e.g. "0 / 500") and enforces that pasted content + existing text does not exceed this limit. */
|
|
83
84
|
maxTextareaCharacters?: number;
|
|
@@ -131,6 +132,7 @@ const Memori: React.FC<Props> = ({
|
|
|
131
132
|
showInputs = true,
|
|
132
133
|
showDates = false,
|
|
133
134
|
showContextPerLine = false,
|
|
135
|
+
showMessageConsumption = false,
|
|
134
136
|
showUpload,
|
|
135
137
|
showLogin,
|
|
136
138
|
showReasoning,
|
|
@@ -372,6 +374,7 @@ const Memori: React.FC<Props> = ({
|
|
|
372
374
|
showUpload,
|
|
373
375
|
showReasoning,
|
|
374
376
|
showContextPerLine,
|
|
377
|
+
showMessageConsumption,
|
|
375
378
|
initialContextVars:
|
|
376
379
|
context ?? getParsedContext(layoutIntegrationConfig.contextVars),
|
|
377
380
|
initialQuestion:
|
|
@@ -540,6 +543,7 @@ Memori.propTypes = {
|
|
|
540
543
|
showInputs: PropTypes.bool,
|
|
541
544
|
showDates: PropTypes.bool,
|
|
542
545
|
showContextPerLine: PropTypes.bool,
|
|
546
|
+
showMessageConsumption: PropTypes.bool,
|
|
543
547
|
showSettings: PropTypes.bool,
|
|
544
548
|
showClear: PropTypes.bool,
|
|
545
549
|
showOnlyLastMessages: PropTypes.bool,
|
package/src/locales/de.json
CHANGED
|
@@ -172,6 +172,7 @@
|
|
|
172
172
|
"pressAndHoldToSpeak": "Zum Sprechen gedrückt halten",
|
|
173
173
|
"microphoneMode": "Mikrofonmodus",
|
|
174
174
|
"hideEmissionsLabel": "Vom Zwilling ausgegebenen Text ausblenden",
|
|
175
|
+
"showMessageConsumptionLabel": "Verbrauch pro Nachricht anzeigen",
|
|
175
176
|
"secondsLabel": "Sekunden einstellen",
|
|
176
177
|
"controlsPosition": "Steuert die Position",
|
|
177
178
|
"tryMeHeaderLabel": "VERSUCHEN",
|
|
@@ -369,6 +370,27 @@
|
|
|
369
370
|
"successfullyLoggedIn": "{{username}} hat sich erfolgreich angemeldet"
|
|
370
371
|
},
|
|
371
372
|
"chatLogs": {
|
|
373
|
+
"llm": "LLM",
|
|
374
|
+
"model": "Modell",
|
|
375
|
+
"provider": "Anbieter",
|
|
376
|
+
"tokens": "Tokens",
|
|
377
|
+
"input": "Eingabe",
|
|
378
|
+
"output": "Ausgabe",
|
|
379
|
+
"cacheRead": "Cache lesen",
|
|
380
|
+
"cacheWrite": "Cache schreiben",
|
|
381
|
+
"duration": "Dauer",
|
|
382
|
+
"energy": "Energie",
|
|
383
|
+
"co2": "CO2",
|
|
384
|
+
"water": "Wasser",
|
|
385
|
+
"usageBadgesHint": "Klicke auf einen dieser Buttons, um mehr Informationen zu sehen",
|
|
386
|
+
"impactComparisonUnavailable": "Indikativer Vergleich nicht verfuegbar.",
|
|
387
|
+
"impactComparisonEnergy": "Indikativer Vergleich: in etwa wie eine 10-W-LED-Lampe fuer {{duration}} eingeschaltet lassen.",
|
|
388
|
+
"impactComparisonCo2": "Indikativer Vergleich: etwa {{distance}} mit einem durchschnittlichen Benzinauto gefahren.",
|
|
389
|
+
"impactComparisonWater": "Indikativer Vergleich: etwa {{count}} Wassertropfen.",
|
|
390
|
+
"energyImpactDescription": "Dieser Wert schaetzt die elektrische Energie, die zur Erzeugung der Modellantwort benoetigt wird. Er hilft, Prompts, Modelle und Strategien zu vergleichen, auch wenn eine einzelne Nachricht nur sehr geringe Auswirkungen hat.",
|
|
391
|
+
"co2ImpactDescription": "CO2-Aequivalent steht fuer die geschaetzten Klimaauswirkungen der Nachricht. Die Umrechnung des Verbrauchs in Emissionen hilft, die Umweltauswirkungen einer KI-Antwort mit vergleichbaren Kennzahlen zu verstehen.",
|
|
392
|
+
"waterImpactDescription": "Dieser Indikator zeigt den geschaetzten Wasserfussabdruck der Nachrichtenverarbeitung. Er umfasst Wasser, das indirekt in Energie und Infrastruktur eingesetzt wird, die die Berechnung ermoeglichen.",
|
|
393
|
+
"approximateValuesTooltip": "Diese Werte sind ungefaehr.",
|
|
372
394
|
"anyMessage": "Jede Nachricht",
|
|
373
395
|
"atLeast": "Mindestens {{count}} Nachrichten",
|
|
374
396
|
"atLeast2": "Mindestens 2 Nachrichten",
|
package/src/locales/en.json
CHANGED
|
@@ -174,6 +174,7 @@
|
|
|
174
174
|
"pressAndHoldToSpeak": "Press and hold to speak",
|
|
175
175
|
"microphoneMode": "Microphone mode",
|
|
176
176
|
"hideEmissionsLabel": "Hide text emitted by the agent",
|
|
177
|
+
"showMessageConsumptionLabel": "Show message consumption",
|
|
177
178
|
"secondsLabel": "Set seconds",
|
|
178
179
|
"controlsPosition": "Controls position",
|
|
179
180
|
"avatarControls": "Avatar controls",
|
|
@@ -440,6 +441,27 @@
|
|
|
440
441
|
"successfullyLoggedIn": "{{username}} has successfully logged in"
|
|
441
442
|
},
|
|
442
443
|
"chatLogs": {
|
|
444
|
+
"llm": "LLM",
|
|
445
|
+
"model": "Model",
|
|
446
|
+
"provider": "Provider",
|
|
447
|
+
"tokens": "Tokens",
|
|
448
|
+
"input": "Input",
|
|
449
|
+
"output": "Output",
|
|
450
|
+
"cacheRead": "Cache read",
|
|
451
|
+
"cacheWrite": "Cache write",
|
|
452
|
+
"duration": "Duration",
|
|
453
|
+
"energy": "Energy",
|
|
454
|
+
"co2": "CO2",
|
|
455
|
+
"water": "Water",
|
|
456
|
+
"usageBadgesHint": "Click one of these buttons to show more information",
|
|
457
|
+
"impactComparisonUnavailable": "Indicative comparison unavailable.",
|
|
458
|
+
"impactComparisonEnergy": "Indicative comparison: roughly like keeping a 10 W LED bulb on for {{duration}}.",
|
|
459
|
+
"impactComparisonCo2": "Indicative comparison: about {{distance}} traveled by an average gasoline car.",
|
|
460
|
+
"impactComparisonWater": "Indicative comparison: about {{count}} drops of water.",
|
|
461
|
+
"energyImpactDescription": "This value estimates the electrical energy needed to generate the model response. It helps compare prompts, models, and strategies even when a single message has a very small impact.",
|
|
462
|
+
"co2ImpactDescription": "CO2 equivalent represents the estimated climate impact of the message. Converting consumption into emissions helps understand AI impact with comparable metrics.",
|
|
463
|
+
"waterImpactDescription": "This indicator shows the estimated water footprint associated with processing the message. It includes water indirectly used by the energy and infrastructure supporting computation.",
|
|
464
|
+
"approximateValuesTooltip": "These values are approximate.",
|
|
443
465
|
"anyMessage": "Any message",
|
|
444
466
|
"atLeast": "At least {{count}} messages",
|
|
445
467
|
"atLeast2": "At least 2 messages",
|
package/src/locales/es.json
CHANGED
|
@@ -172,6 +172,7 @@
|
|
|
172
172
|
"pressAndHoldToSpeak": "Mantenga presionado para hablar",
|
|
173
173
|
"microphoneMode": "Modo micrófono",
|
|
174
174
|
"hideEmissionsLabel": "Ocultar texto emitido por el Agent",
|
|
175
|
+
"showMessageConsumptionLabel": "Mostrar consumo por mensaje",
|
|
175
176
|
"secondsLabel": "Establecer segundos",
|
|
176
177
|
"controlsPosition": "Posición de los controles",
|
|
177
178
|
"tryMeHeaderLabel": "INTENTAR",
|
|
@@ -396,6 +397,27 @@
|
|
|
396
397
|
"successfullyLoggedIn": "{{username}} ha iniciado sesión correctamente"
|
|
397
398
|
},
|
|
398
399
|
"chatLogs": {
|
|
400
|
+
"llm": "LLM",
|
|
401
|
+
"model": "Modelo",
|
|
402
|
+
"provider": "Proveedor",
|
|
403
|
+
"tokens": "Tokens",
|
|
404
|
+
"input": "Entrada",
|
|
405
|
+
"output": "Salida",
|
|
406
|
+
"cacheRead": "Lectura de caché",
|
|
407
|
+
"cacheWrite": "Escritura de caché",
|
|
408
|
+
"duration": "Duración",
|
|
409
|
+
"energy": "Energía",
|
|
410
|
+
"co2": "CO2",
|
|
411
|
+
"water": "Agua",
|
|
412
|
+
"usageBadgesHint": "Haz clic en uno de estos botones para ver más información",
|
|
413
|
+
"impactComparisonUnavailable": "Comparacion indicativa no disponible.",
|
|
414
|
+
"impactComparisonEnergy": "Comparacion indicativa: aproximadamente como mantener encendida una bombilla LED de 10 W durante {{duration}}.",
|
|
415
|
+
"impactComparisonCo2": "Comparacion indicativa: aproximadamente {{distance}} recorridos en un coche de gasolina promedio.",
|
|
416
|
+
"impactComparisonWater": "Comparacion indicativa: aproximadamente {{count}} gotas de agua.",
|
|
417
|
+
"energyImpactDescription": "Este valor estima la energia electrica necesaria para generar la respuesta del modelo. Sirve para comparar prompts, modelos y estrategias incluso cuando un solo mensaje tiene un impacto muy pequeno.",
|
|
418
|
+
"co2ImpactDescription": "El CO2 equivalente representa el impacto climatico estimado del mensaje. Traducir el consumo a emisiones ayuda a entender cuanto pesa una respuesta de IA en el medioambiente con metricas comparables.",
|
|
419
|
+
"waterImpactDescription": "Este indicador muestra la huella hidrica estimada asociada al procesamiento del mensaje. Incluye el agua utilizada indirectamente en la energia y en la infraestructura que soporta el calculo.",
|
|
420
|
+
"approximateValuesTooltip": "Estos valores son aproximados.",
|
|
399
421
|
"anyMessage": "Cualquier mensaje",
|
|
400
422
|
"atLeast": "Al menos {{count}} mensajes",
|
|
401
423
|
"atLeast2": "Al menos 2 mensajes",
|
package/src/locales/fr.json
CHANGED
|
@@ -180,6 +180,7 @@
|
|
|
180
180
|
"pressAndHoldToSpeak": "Appuyez et maintenez pour parler",
|
|
181
181
|
"microphoneMode": "Mode micro",
|
|
182
182
|
"hideEmissionsLabel": "Masquer le texte émis par le Agent",
|
|
183
|
+
"showMessageConsumptionLabel": "Afficher la consommation par message",
|
|
183
184
|
"secondsLabel": "Régler les secondes",
|
|
184
185
|
"controlsPosition": "Position des commandes",
|
|
185
186
|
"tryMeHeaderLabel": "ESSAYER",
|
|
@@ -404,6 +405,27 @@
|
|
|
404
405
|
"successfullyLoggedIn": "{{username}} s'est connecté avec succès"
|
|
405
406
|
},
|
|
406
407
|
"chatLogs": {
|
|
408
|
+
"llm": "LLM",
|
|
409
|
+
"model": "Modèle",
|
|
410
|
+
"provider": "Fournisseur",
|
|
411
|
+
"tokens": "Tokens",
|
|
412
|
+
"input": "Entrée",
|
|
413
|
+
"output": "Sortie",
|
|
414
|
+
"cacheRead": "Lecture cache",
|
|
415
|
+
"cacheWrite": "Écriture cache",
|
|
416
|
+
"duration": "Durée",
|
|
417
|
+
"energy": "Énergie",
|
|
418
|
+
"co2": "CO2",
|
|
419
|
+
"water": "Eau",
|
|
420
|
+
"usageBadgesHint": "Cliquez sur un de ces boutons pour afficher plus d'informations",
|
|
421
|
+
"impactComparisonUnavailable": "Comparaison indicative non disponible.",
|
|
422
|
+
"impactComparisonEnergy": "Comparaison indicative : environ comme laisser allumee une ampoule LED de 10 W pendant {{duration}}.",
|
|
423
|
+
"impactComparisonCo2": "Comparaison indicative : environ {{distance}} parcourus en voiture essence moyenne.",
|
|
424
|
+
"impactComparisonWater": "Comparaison indicative : environ {{count}} gouttes d'eau.",
|
|
425
|
+
"energyImpactDescription": "Cette valeur estime l'energie electrique necessaire pour generer la reponse du modele. Elle permet de comparer prompts, modeles et strategies meme quand l'impact d'un seul message est tres faible.",
|
|
426
|
+
"co2ImpactDescription": "Le CO2 equivalent represente l'impact climatique estime du message. Traduire la consommation en emissions aide a comprendre le poids environnemental d'une reponse IA avec des mesures comparables.",
|
|
427
|
+
"waterImpactDescription": "Cet indicateur montre l'empreinte hydrique estimee associee au traitement du message. Il inclut l'eau utilisee indirectement par l'energie et l'infrastructure qui soutiennent le calcul.",
|
|
428
|
+
"approximateValuesTooltip": "Ces valeurs sont approximatives.",
|
|
407
429
|
"anyMessage": "Tout message",
|
|
408
430
|
"atLeast": "Au moins {{count}} messages",
|
|
409
431
|
"atLeast2": "Au moins 2 messages",
|
package/src/locales/it.json
CHANGED
|
@@ -177,6 +177,7 @@
|
|
|
177
177
|
"pressAndHoldToSpeak": "Premi e tieni premuto per parlare",
|
|
178
178
|
"microphoneMode": "Modalità microfono",
|
|
179
179
|
"hideEmissionsLabel": "Nascondi testo emesso dall'agente",
|
|
180
|
+
"showMessageConsumptionLabel": "Mostra consumo per messaggio",
|
|
180
181
|
"secondsLabel": "Secondi",
|
|
181
182
|
"controlsPosition": "Posizione dei controlli",
|
|
182
183
|
"avatarControls": "Controlli Avatar",
|
|
@@ -437,6 +438,27 @@
|
|
|
437
438
|
"successfullyLoggedIn": "{{username}} ha effettuato l'accesso con successo"
|
|
438
439
|
},
|
|
439
440
|
"chatLogs": {
|
|
441
|
+
"llm": "LLM",
|
|
442
|
+
"model": "Modello",
|
|
443
|
+
"provider": "Provider",
|
|
444
|
+
"tokens": "Token",
|
|
445
|
+
"input": "Input",
|
|
446
|
+
"output": "Output",
|
|
447
|
+
"cacheRead": "Cache read",
|
|
448
|
+
"cacheWrite": "Cache write",
|
|
449
|
+
"duration": "Durata",
|
|
450
|
+
"energy": "Energia",
|
|
451
|
+
"co2": "CO2",
|
|
452
|
+
"water": "Acqua",
|
|
453
|
+
"usageBadgesHint": "Clicca uno di questi pulsanti per mostrare maggiori informazioni",
|
|
454
|
+
"impactComparisonUnavailable": "Confronto indicativo non disponibile.",
|
|
455
|
+
"impactComparisonEnergy": "Confronto indicativo: circa quanto tenere accesa una lampadina LED da 10 W per {{duration}}.",
|
|
456
|
+
"impactComparisonCo2": "Confronto indicativo: circa {{distance}} percorsi in auto a benzina media.",
|
|
457
|
+
"impactComparisonWater": "Confronto indicativo: circa {{count}} gocce d'acqua.",
|
|
458
|
+
"energyImpactDescription": "Questo valore stima l'energia elettrica necessaria per generare la risposta del modello. Serve a confrontare prompt, modelli e strategie diverse anche quando il singolo messaggio ha un impatto molto piccolo.",
|
|
459
|
+
"co2ImpactDescription": "La CO2 equivalente rappresenta l'impatto climatico stimato del messaggio. Tradurre il consumo in emissioni aiuta a capire quanto una risposta AI pesa sull'ambiente in termini comparabili.",
|
|
460
|
+
"waterImpactDescription": "Questo indicatore mostra l'impronta idrica stimata associata all'elaborazione del messaggio. Include l'acqua impiegata indirettamente nell'energia e nell'infrastruttura che supportano il calcolo.",
|
|
461
|
+
"approximateValuesTooltip": "Questi valori sono approssimativi.",
|
|
440
462
|
"atLeast": "Almeno {{count}} messaggi",
|
|
441
463
|
"anyMessage": "Qualunque messaggio",
|
|
442
464
|
"atLeast2": "Almeno 2 messaggi",
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated. Do not edit manually.
|
|
2
|
-
export const version = '8.
|
|
2
|
+
export const version = '8.30.0';
|