diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 0a6d325c3e..6579e7a40e 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -5642,7 +5642,7 @@ packages: version: 0.0.0 '@rush-temp/pod-ai-bot@file:projects/pod-ai-bot.tgz': - resolution: {integrity: sha512-i7ARoUNEidIH+C+xWIrmtTsSR88zlHArLoCwIjeuC5NjjAgd5erkDkPL9IyJ3hwSFjAZ+V0TTtOVLJavcs03ZA==, tarball: file:projects/pod-ai-bot.tgz} + resolution: {integrity: sha512-LQ42nJT9Obn8nZgE5e5XKErxbtZj2LxZs3IvE9xPMW179nVDdQFAc9fGlZ7adrmCvYpRPpNIgXV2O9rimBeL5g==, tarball: file:projects/pod-ai-bot.tgz} version: 0.0.0 '@rush-temp/pod-analytics-collector@file:projects/pod-analytics-collector.tgz': @@ -5754,7 +5754,7 @@ packages: version: 0.0.0 '@rush-temp/pod-translate@file:projects/pod-translate.tgz': - resolution: {integrity: sha512-YWZPxkubAeu8Se4YwOfZept8ufirQy4ndQ1N+QD9EUAla6VUuRPC0zhcG1Vl3LGKAp9hUR9bZTy0EIPdFHY/AA==, tarball: file:projects/pod-translate.tgz} + resolution: {integrity: sha512-cdak2NAfd+s4CAv3kGdBPeAgM5o/QJCH2OYfS6NI8GhTL0BsdmbiLbn2hQxzpRlpCBFnvOaUzO6HcFUa0owrcA==, tarball: file:projects/pod-translate.tgz} version: 0.0.0 '@rush-temp/pod-worker@file:projects/pod-worker.tgz': @@ -27302,6 +27302,7 @@ snapshots: '@hcengineering/platform': 0.7.5 '@hcengineering/platform-rig': 0.7.19(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.5.3)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.9.3)))(postcss@8.5.3)(sass@1.93.2)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.9.3)) '@hcengineering/rank': 0.7.5 + '@hcengineering/retry': 0.7.5 '@hcengineering/server-client': 0.7.8(bufferutil@4.0.8)(utf-8-validate@6.0.4) '@hcengineering/server-core': 0.7.8 '@hcengineering/server-storage': 0.7.9 diff --git a/packages/billing-client/src/client.ts b/packages/billing-client/src/client.ts index a0263dd11a..f427d545a1 100644 --- a/packages/billing-client/src/client.ts +++ b/packages/billing-client/src/client.ts @@ -1,6 +1,8 @@ import { concatLink, WorkspaceUuid } from '@hcengineering/core' import { BillingError, NetworkError } from './error' import { + AiTokensData, + AiTranscriptData, BillingStats, DatalakeStats, LiveKitEgressData, @@ -83,6 +85,29 @@ export class BillingClient { const body = JSON.stringify(egress) await fetchSafe(url, { method: 'POST', headers: { ...this.headers }, body }) } + + async getAiTranscriptLastData (): Promise { + const path = '/api/v1/ai/transcript/last' + const url = new URL(concatLink(this.endpoint, path)) + const response = await fetchSafe(url, { headers: { ...this.headers } }) + return (await response.json()) as AiTranscriptData | undefined + } + + async postAiTranscriptData (data: AiTranscriptData[]): Promise { + const path = '/api/v1/ai/transcript' + const url = new URL(concatLink(this.endpoint, path)) + const body = JSON.stringify(data) + + await fetchSafe(url, { method: 'POST', headers: { ...this.headers }, body }) + } + + async postAiTokensData (data: AiTokensData[]): Promise { + const path = '/api/v1/ai/tokens' + const url = new URL(concatLink(this.endpoint, path)) + const body = JSON.stringify(data) + + await fetchSafe(url, { method: 'POST', headers: { ...this.headers }, body }) + } } async function fetchSafe (url: string | URL, init?: RequestInit): Promise { diff --git a/packages/billing-client/src/types.ts b/packages/billing-client/src/types.ts index 1dc732542b..8edcd6119c 100644 --- a/packages/billing-client/src/types.ts +++ b/packages/billing-client/src/types.ts @@ -1,6 +1,9 @@ +import { WorkspaceUuid } from '@hcengineering/core' + export interface BillingStats { liveKitStats: LiveKitStats datalakeStats: DatalakeStats + aiStats: AiStats } export interface DatalakeStats { @@ -42,3 +45,33 @@ export interface LiveKitEgressData { egressEnd: string duration: number } + +export interface AiTranscriptStats { + totalDurationSeconds: number +} + +export interface AiTokensStats { + reason: string + totalTokens: number +} + +export interface AiStats { + transcript: AiTranscriptStats + tokens: AiTokensStats[] +} + +export interface AiTranscriptData { + workspace: WorkspaceUuid + day: string + lastRequestId: string + lastStartTime: string + durationSeconds: number + usd: number +} + +export interface AiTokensData { + workspace: WorkspaceUuid + reason: string + tokens: number + date: string +} diff --git a/packages/ui/src/utils.ts b/packages/ui/src/utils.ts index 5e59cd6659..a8a2064a14 100644 --- a/packages/ui/src/utils.ts +++ b/packages/ui/src/utils.ts @@ -355,6 +355,14 @@ export async function formatDuration (duration: number, language: string): Promi return text } +export function formatNumberCompact (num: number, maximumFractionDigits = 2): string { + const locale = new Intl.NumberFormat().resolvedOptions().locale + return new Intl.NumberFormat(locale, { + notation: 'compact', + maximumFractionDigits + }).format(num) +} + export function pushRootBarComponent (pos: 'left' | 'right', component: AnyComponent, order?: number): void { rootBarExtensions.update((cur) => { if (cur.find((p) => p[1].component === component) === undefined) { diff --git a/plugins/billing-assets/lang/cs.json b/plugins/billing-assets/lang/cs.json index d306274cc8..86ed0caecd 100644 --- a/plugins/billing-assets/lang/cs.json +++ b/plugins/billing-assets/lang/cs.json @@ -5,6 +5,9 @@ "DriveCount": "Počet souborů", "OfficeSessionsDuration": "Doba schůzek", "OfficeSessionsBandwidth": "Šířka pásma schůzek", - "OfficeEgressDuration": "Doba záznamu" + "OfficeEgressDuration": "Doba záznamu", + "AI": "AI", + "TranscriptionTime": "Doba přepisu", + "TotalTokens": "Celkem tokenů" } } diff --git a/plugins/billing-assets/lang/de.json b/plugins/billing-assets/lang/de.json index 1fdd9715cf..86befc9986 100644 --- a/plugins/billing-assets/lang/de.json +++ b/plugins/billing-assets/lang/de.json @@ -5,6 +5,9 @@ "DriveCount": "Dateianzahl", "OfficeSessionsDuration": "Besprechungsdauer", "OfficeSessionsBandwidth": "Besprechungsbandbreite", - "OfficeEgressDuration": "Aufzeichnungsdauer" + "OfficeEgressDuration": "Aufzeichnungsdauer", + "AI": "AI", + "TranscriptionTime": "Transkriptionszeit", + "TotalTokens": "Gesamte Tokens" } } diff --git a/plugins/billing-assets/lang/en.json b/plugins/billing-assets/lang/en.json index 1d45d97f07..2d277cc69b 100644 --- a/plugins/billing-assets/lang/en.json +++ b/plugins/billing-assets/lang/en.json @@ -5,6 +5,9 @@ "DriveCount": "Files count", "OfficeSessionsDuration": "Meetings time", "OfficeSessionsBandwidth": "Meetings bandwidth", - "OfficeEgressDuration": "Recording time" + "OfficeEgressDuration": "Recording time", + "AI": "AI", + "TranscriptionTime": "Transcription time", + "TotalTokens": "Total tokens" } } diff --git a/plugins/billing-assets/lang/es.json b/plugins/billing-assets/lang/es.json index d0ea62ca07..d8ad2d2f7a 100644 --- a/plugins/billing-assets/lang/es.json +++ b/plugins/billing-assets/lang/es.json @@ -5,6 +5,9 @@ "DriveCount": "Cantidad de archivos", "OfficeSessionsDuration": "Tiempo de reuniones", "OfficeSessionsBandwidth": "Ancho de banda de reuniones", - "OfficeEgressDuration": "Tiempo de grabación" + "OfficeEgressDuration": "Tiempo de grabación", + "AI": "IA", + "TranscriptionTime": "Tiempo de transcripción", + "TotalTokens": "Total de tokens" } } diff --git a/plugins/billing-assets/lang/fr.json b/plugins/billing-assets/lang/fr.json index 14219d6b8e..facccb5b1e 100644 --- a/plugins/billing-assets/lang/fr.json +++ b/plugins/billing-assets/lang/fr.json @@ -5,6 +5,9 @@ "DriveCount": "Nombre de fichiers", "OfficeSessionsDuration": "Durée des réunions", "OfficeSessionsBandwidth": "Bande passante des réunions", - "OfficeEgressDuration": "Durée d'enregistrement" + "OfficeEgressDuration": "Durée d'enregistrement", + "AI": "IA", + "TranscriptionTime": "Durée de transcription", + "TotalTokens": "Nombre total de jetons" } } diff --git a/plugins/billing-assets/lang/it.json b/plugins/billing-assets/lang/it.json index 76913ccc55..b62c19cb38 100644 --- a/plugins/billing-assets/lang/it.json +++ b/plugins/billing-assets/lang/it.json @@ -5,6 +5,9 @@ "DriveCount": "Conteggio file", "OfficeSessionsDuration": "Durata riunioni", "OfficeSessionsBandwidth": "Larghezza di banda riunioni", - "OfficeEgressDuration": "Durata registrazione" + "OfficeEgressDuration": "Durata registrazione", + "AI": "AI", + "TranscriptionTime": "Tempo di trascrizione", + "TotalTokens": "Totale token" } } diff --git a/plugins/billing-assets/lang/ja.json b/plugins/billing-assets/lang/ja.json index 3e8ae183fe..d5abbc891c 100644 --- a/plugins/billing-assets/lang/ja.json +++ b/plugins/billing-assets/lang/ja.json @@ -5,6 +5,9 @@ "DriveCount": "ファイル数", "OfficeSessionsDuration": "会議時間", "OfficeSessionsBandwidth": "会議帯域幅", - "OfficeEgressDuration": "録画時間" + "OfficeEgressDuration": "録画時間", + "AI": "AI", + "TranscriptionTime": "文字起こし時間", + "TotalTokens": "合計トークン" } } diff --git a/plugins/billing-assets/lang/pt.json b/plugins/billing-assets/lang/pt.json index 61909d6112..50c416f102 100644 --- a/plugins/billing-assets/lang/pt.json +++ b/plugins/billing-assets/lang/pt.json @@ -5,6 +5,9 @@ "DriveCount": "Quantidade de arquivos", "OfficeSessionsDuration": "Tempo de reuniões", "OfficeSessionsBandwidth": "Largura de banda de reuniões", - "OfficeEgressDuration": "Tempo de gravação" + "OfficeEgressDuration": "Tempo de gravação", + "AI": "IA", + "TranscriptionTime": "Tempo de transcrição", + "TotalTokens": "Total de tokens" } } diff --git a/plugins/billing-assets/lang/ru.json b/plugins/billing-assets/lang/ru.json index 3e306a7e82..c69d491fa1 100644 --- a/plugins/billing-assets/lang/ru.json +++ b/plugins/billing-assets/lang/ru.json @@ -5,6 +5,9 @@ "DriveCount": "Количество файлов", "OfficeSessionsDuration": "Время встреч", "OfficeSessionsBandwidth": "Трафик встреч", - "OfficeEgressDuration": "Время записи" + "OfficeEgressDuration": "Время записи", + "AI": "AI", + "TranscriptionTime": "Время транскрипции", + "TotalTokens": "Всего токенов" } } diff --git a/plugins/billing-assets/lang/tr.json b/plugins/billing-assets/lang/tr.json index b5c843100f..d6576199f7 100644 --- a/plugins/billing-assets/lang/tr.json +++ b/plugins/billing-assets/lang/tr.json @@ -5,6 +5,9 @@ "DriveCount": "Dosya sayısı", "OfficeSessionsDuration": "Toplantı süresi", "OfficeSessionsBandwidth": "Toplantı bant genişliği", - "OfficeEgressDuration": "Kayıt süresi" + "OfficeEgressDuration": "Kayıt süresi", + "AI": "AI", + "TranscriptionTime": "Transkripsiyon süresi", + "TotalTokens": "Toplam belirteçler" } } diff --git a/plugins/billing-assets/lang/zh.json b/plugins/billing-assets/lang/zh.json index 5d1507d4b7..8bdcdcda03 100644 --- a/plugins/billing-assets/lang/zh.json +++ b/plugins/billing-assets/lang/zh.json @@ -5,6 +5,9 @@ "DriveCount": "文件数量", "OfficeSessionsDuration": "会议时间", "OfficeSessionsBandwidth": "会议带宽", - "OfficeEgressDuration": "录制时间" + "OfficeEgressDuration": "录制时间", + "AI": "AI", + "TranscriptionTime": "转录时间", + "TotalTokens": "总令牌数" } } diff --git a/plugins/billing-resources/src/components/Settings.svelte b/plugins/billing-resources/src/components/Settings.svelte index 01ecf4c62e..84c0130ee2 100644 --- a/plugins/billing-resources/src/components/Settings.svelte +++ b/plugins/billing-resources/src/components/Settings.svelte @@ -13,15 +13,25 @@ // limitations under the License. -->