diff --git a/web/src/app/infra/http/BackendClient.ts b/web/src/app/infra/http/BackendClient.ts index b340d0025..c7f09e9af 100644 --- a/web/src/app/infra/http/BackendClient.ts +++ b/web/src/app/infra/http/BackendClient.ts @@ -2166,9 +2166,7 @@ export class BackendClient extends BaseHttpClient { queryParams.append('offset', params.offset.toString()); } - return this.get( - `/api/v1/monitoring/executions?${queryParams.toString()}`, - ); + return this.get(`/api/v1/monitoring/executions?${queryParams.toString()}`); } public getExecutionDetail( diff --git a/web/src/i18n/locales/en-US.ts b/web/src/i18n/locales/en-US.ts index e4f016e27..d4dabf0ae 100644 --- a/web/src/i18n/locales/en-US.ts +++ b/web/src/i18n/locales/en-US.ts @@ -2481,7 +2481,12 @@ const enUS = { cancelled: 'Cancelled', ignored: 'Ignored', }, - kind: { agent: 'Agent', pipeline: 'Pipeline', processor: 'Processor' }, + // prettier-ignore + kind: { + agent: 'Agent', + pipeline: 'Pipeline', + processor: 'Processor', + }, columns: { time: 'Time', target: 'Processor', diff --git a/web/src/i18n/locales/es-ES.ts b/web/src/i18n/locales/es-ES.ts index ec77461cb..5b12669df 100644 --- a/web/src/i18n/locales/es-ES.ts +++ b/web/src/i18n/locales/es-ES.ts @@ -2508,6 +2508,88 @@ const esES = { }, }, monitoring: { + execution: { + title: 'Ejecuciones', + subtitle: + 'Cada evento entrante y la ejecución que activó, en agentes y pipelines.', + tabs: { executions: 'Ejecuciones' }, + filters: { + source: 'Tipo', + sourceAll: 'Todos los tipos', + sourceAgent: 'Agentes', + sourcePipeline: 'Pipelines', + mode: 'Tráfico', + modeAll: 'Real + depuración', + modeLive: 'Solo real', + modeDebug: 'Solo depuración', + status: 'Estado', + statusAll: 'Todos los estados', + }, + status: { + completed: 'Completada', + failed: 'Fallida', + running: 'En curso', + queued: 'En cola', + cancelled: 'Cancelada', + ignored: 'Ignorada', + }, + // prettier-ignore + kind: { + agent: 'Agente', + pipeline: 'Pipeline', + processor: 'Procesador', + }, + columns: { + time: 'Hora', + target: 'Procesador', + status: 'Estado', + duration: 'Duración', + tokens: 'Tokens', + }, + debug: 'Depuración', + empty: 'No hay ejecuciones en este intervalo', + loading: 'Cargando ejecuciones...', + triggeredBy: 'Activada por {{trigger}}', + cards: { + totalExecutions: 'Ejecuciones', + bySource: '{{agent}} de agentes · {{pipeline}} de pipelines', + successRate: 'Tasa de éxito de ejecución', + successRateHint: + 'Completadas ÷ (completadas + fallidas). Se excluyen del denominador los eventos ignorados y las ejecuciones en curso.', + denominator: '{{completed}} de {{denominator}} finalizadas', + running: 'En curso', + queued: 'En cola', + waiting: 'Esperando entrada', + failed: 'Fallida', + ignored: 'Ignorada', + latency: 'Duración P50 / P95', + p50: 'P50', + p95: 'P95', + sample: 'muestra de {{count}} ejecuciones', + tokens: 'Tokens', + coverage: 'uso registrado en {{withUsage}}/{{calls}} llamadas', + hiddenDebug: '{{count}} ejecuciones de depuración ocultas', + }, + detail: { + title: 'Ejecución', + timeline: 'Cronología', + executionId: 'ID de ejecución', + eventId: 'Evento', + queue: 'Cola', + runner: 'Runner', + created: 'Creada', + duration: 'Duración', + usage: 'Uso', + noEvents: 'No se registraron eventos de traza', + query: 'Mensaje entrante', + modelCalls: 'Llamadas al modelo', + toolCalls: 'Llamadas a herramientas', + errors: 'Errores', + loadError: 'No se pudo cargar la traza de ejecución', + openObject: 'Abrir objeto', + a11yDescription: 'Traza completa de esta ejecución', + }, + }, title: 'Panel de control', description: 'Monitorea las actividades de los Bots, llamadas LLM y rendimiento del sistema', diff --git a/web/src/i18n/locales/ja-JP.ts b/web/src/i18n/locales/ja-JP.ts index f24e83328..c4df409a9 100644 --- a/web/src/i18n/locales/ja-JP.ts +++ b/web/src/i18n/locales/ja-JP.ts @@ -2472,6 +2472,88 @@ const jaJP = { }, }, monitoring: { + execution: { + title: '実行履歴', + subtitle: + 'エージェントとパイプラインに届いた各イベントと、それによって開始された実行を確認します。', + tabs: { executions: '実行履歴' }, + filters: { + source: '種類', + sourceAll: 'すべての種類', + sourceAgent: 'エージェント', + sourcePipeline: 'パイプライン', + mode: '実行モード', + modeAll: '通常+デバッグ', + modeLive: '通常のみ', + modeDebug: 'デバッグのみ', + status: '状態', + statusAll: 'すべての状態', + }, + status: { + completed: '完了', + failed: '失敗', + running: '実行中', + queued: '待機中', + cancelled: 'キャンセル済み', + ignored: '無視', + }, + // prettier-ignore + kind: { + agent: 'エージェント', + pipeline: 'パイプライン', + processor: '処理対象', + }, + columns: { + time: '時刻', + target: '処理対象', + status: '状態', + duration: '所要時間', + tokens: 'トークン', + }, + debug: 'デバッグ', + empty: 'この期間の実行履歴はありません', + loading: '実行履歴を読み込み中...', + triggeredBy: '{{trigger}} により開始', + cards: { + totalExecutions: '実行履歴', + bySource: 'エージェント {{agent}} 件 · パイプライン {{pipeline}} 件', + successRate: '実行成功率', + successRateHint: + '完了 ÷(完了+失敗)。無視されたイベントと実行中の処理は分母に含まれません。', + denominator: '終了済み {{denominator}} 件中 {{completed}} 件が完了', + running: '実行中', + queued: '待機中', + waiting: '入力待ち', + failed: '失敗', + ignored: '無視', + latency: '所要時間 P50 / P95', + p50: 'P50', + p95: 'P95', + sample: '{{count}} 件の実行を集計', + tokens: 'トークン', + coverage: '{{calls}} 回中 {{withUsage}} 回で使用量を取得', + hiddenDebug: 'デバッグ実行 {{count}} 件を非表示', + }, + detail: { + title: '実行', + timeline: 'タイムライン', + executionId: '実行 ID', + eventId: 'イベント', + queue: 'キュー', + runner: 'ランナー', + created: '作成日時', + duration: '所要時間', + usage: '使用量', + noEvents: '記録されたトレースイベントはありません', + query: '受信メッセージ', + modelCalls: 'モデル呼び出し', + toolCalls: 'ツール呼び出し', + errors: 'エラー', + loadError: '実行トレースを読み込めませんでした', + openObject: '対象を開く', + a11yDescription: 'この実行の完全なトレース', + }, + }, title: 'ダッシュボード', description: 'ボットアクティビティ、LLM呼び出し、システムパフォーマンスを監視', diff --git a/web/src/i18n/locales/ru-RU.ts b/web/src/i18n/locales/ru-RU.ts index 9bcbe1158..7c16a5b33 100644 --- a/web/src/i18n/locales/ru-RU.ts +++ b/web/src/i18n/locales/ru-RU.ts @@ -2480,6 +2480,88 @@ const ruRU = { }, }, monitoring: { + execution: { + title: 'Выполнения', + subtitle: + 'Все входящие события и вызванные ими выполнения агентов и конвейеров.', + tabs: { executions: 'Выполнения' }, + filters: { + source: 'Тип', + sourceAll: 'Все типы', + sourceAgent: 'Агенты', + sourcePipeline: 'Конвейеры', + mode: 'Режим выполнения', + modeAll: 'Обычные и отладочные', + modeLive: 'Только обычные', + modeDebug: 'Только отладочные', + status: 'Статус', + statusAll: 'Все статусы', + }, + status: { + completed: 'Завершено', + failed: 'Ошибка', + running: 'Выполняется', + queued: 'В очереди', + cancelled: 'Отменено', + ignored: 'Пропущено', + }, + // prettier-ignore + kind: { + agent: 'Агент', + pipeline: 'Конвейер', + processor: 'Обработчик', + }, + columns: { + time: 'Время', + target: 'Обработчик', + status: 'Статус', + duration: 'Длительность', + tokens: 'Токены', + }, + debug: 'Отладка', + empty: 'За этот период выполнений нет', + loading: 'Загрузка выполнений...', + triggeredBy: 'Запущено: {{trigger}}', + cards: { + totalExecutions: 'Выполнения', + bySource: 'Агенты: {{agent}} · Конвейеры: {{pipeline}}', + successRate: 'Доля успешных выполнений', + successRateHint: + 'Завершённые ÷ (завершённые + неудачные). Пропущенные события и незавершённые выполнения не входят в знаменатель.', + denominator: 'Успешно: {{completed}} из {{denominator}} завершившихся', + running: 'Выполняется', + queued: 'В очереди', + waiting: 'Ожидание ввода', + failed: 'Ошибка', + ignored: 'Пропущено', + latency: 'Длительность P50 / P95', + p50: 'P50', + p95: 'P95', + sample: 'выборка: {{count}} выполнений', + tokens: 'Токены', + coverage: 'расход указан для {{withUsage}}/{{calls}} вызовов', + hiddenDebug: 'Скрыто отладочных выполнений: {{count}}', + }, + detail: { + title: 'Выполнение', + timeline: 'Хронология', + executionId: 'ID выполнения', + eventId: 'Событие', + queue: 'Очередь', + runner: 'Исполнитель', + created: 'Создано', + duration: 'Длительность', + usage: 'Расход', + noEvents: 'События трассировки не записаны', + query: 'Входящее сообщение', + modelCalls: 'Вызовы моделей', + toolCalls: 'Вызовы инструментов', + errors: 'Ошибки', + loadError: 'Не удалось загрузить трассировку выполнения', + openObject: 'Открыть объект', + a11yDescription: 'Полная трассировка этого выполнения', + }, + }, title: 'Мониторинг', description: 'Мониторинг активности ботов, вызовов LLM и производительности системы', diff --git a/web/src/i18n/locales/th-TH.ts b/web/src/i18n/locales/th-TH.ts index d1b7be940..aa8636f35 100644 --- a/web/src/i18n/locales/th-TH.ts +++ b/web/src/i18n/locales/th-TH.ts @@ -2407,6 +2407,89 @@ const thTH = { }, }, monitoring: { + execution: { + title: 'การทำงาน', + subtitle: + 'เหตุการณ์ขาเข้าแต่ละรายการและการทำงานที่ถูกเรียกใช้ ทั้งในเอเจนต์และไปป์ไลน์', + tabs: { executions: 'การทำงาน' }, + filters: { + source: 'ประเภท', + sourceAll: 'ทุกประเภท', + sourceAgent: 'เอเจนต์', + sourcePipeline: 'ไปป์ไลน์', + mode: 'โหมดการทำงาน', + modeAll: 'ใช้งานจริง + ดีบัก', + modeLive: 'เฉพาะใช้งานจริง', + modeDebug: 'เฉพาะดีบัก', + status: 'สถานะ', + statusAll: 'ทุกสถานะ', + }, + status: { + completed: 'เสร็จสิ้น', + failed: 'ล้มเหลว', + running: 'กำลังทำงาน', + queued: 'อยู่ในคิว', + cancelled: 'ยกเลิกแล้ว', + ignored: 'ละเว้นแล้ว', + }, + // prettier-ignore + kind: { + agent: 'เอเจนต์', + pipeline: 'ไปป์ไลน์', + processor: 'ตัวประมวลผล', + }, + columns: { + time: 'เวลา', + target: 'ตัวประมวลผล', + status: 'สถานะ', + duration: 'ระยะเวลา', + tokens: 'โทเคน', + }, + debug: 'ดีบัก', + empty: 'ไม่มีการทำงานในช่วงเวลานี้', + loading: 'กำลังโหลดการทำงาน...', + triggeredBy: 'เรียกใช้โดย {{trigger}}', + cards: { + totalExecutions: 'การทำงาน', + bySource: 'เอเจนต์ {{agent}} · ไปป์ไลน์ {{pipeline}}', + successRate: 'อัตราการทำงานสำเร็จ', + successRateHint: + 'เสร็จสิ้น ÷ (เสร็จสิ้น + ล้มเหลว) ไม่นับเหตุการณ์ที่ละเว้นและการทำงานที่ยังไม่สิ้นสุดในตัวหาร', + denominator: + 'สำเร็จ {{completed}} จาก {{denominator}} รายการที่สิ้นสุดแล้ว', + running: 'กำลังทำงาน', + queued: 'อยู่ในคิว', + waiting: 'รอการป้อนข้อมูล', + failed: 'ล้มเหลว', + ignored: 'ละเว้นแล้ว', + latency: 'ระยะเวลา P50 / P95', + p50: 'P50', + p95: 'P95', + sample: 'ตัวอย่างการทำงาน {{count}} ครั้ง', + tokens: 'โทเคน', + coverage: 'มีข้อมูลการใช้งาน {{withUsage}}/{{calls}} ครั้ง', + hiddenDebug: 'ซ่อนการทำงานดีบัก {{count}} ครั้ง', + }, + detail: { + title: 'การทำงาน', + timeline: 'ลำดับเวลา', + executionId: 'ID การทำงาน', + eventId: 'เหตุการณ์', + queue: 'คิว', + runner: 'รันเนอร์', + created: 'สร้างเมื่อ', + duration: 'ระยะเวลา', + usage: 'การใช้งาน', + noEvents: 'ไม่มีการบันทึกเหตุการณ์ติดตาม', + query: 'ข้อความขาเข้า', + modelCalls: 'การเรียกใช้โมเดล', + toolCalls: 'การเรียกใช้เครื่องมือ', + errors: 'ข้อผิดพลาด', + loadError: 'โหลดการติดตามการทำงานไม่สำเร็จ', + openObject: 'เปิดรายการ', + a11yDescription: 'การติดตามทั้งหมดของการทำงานนี้', + }, + }, title: 'แดชบอร์ด', description: 'ตรวจสอบกิจกรรม Bot, การเรียก LLM และประสิทธิภาพของระบบ', overview: 'ภาพรวม', diff --git a/web/src/i18n/locales/vi-VN.ts b/web/src/i18n/locales/vi-VN.ts index f3e72f46d..fa719f4e5 100644 --- a/web/src/i18n/locales/vi-VN.ts +++ b/web/src/i18n/locales/vi-VN.ts @@ -2442,6 +2442,89 @@ const viVN = { }, }, monitoring: { + execution: { + title: 'Lượt thực thi', + subtitle: + 'Mọi sự kiện đầu vào và lượt thực thi được kích hoạt trên các tác nhân và pipeline.', + tabs: { executions: 'Lượt thực thi' }, + filters: { + source: 'Loại', + sourceAll: 'Tất cả loại', + sourceAgent: 'Tác nhân', + sourcePipeline: 'Pipeline', + mode: 'Chế độ thực thi', + modeAll: 'Thực tế + gỡ lỗi', + modeLive: 'Chỉ thực tế', + modeDebug: 'Chỉ gỡ lỗi', + status: 'Trạng thái', + statusAll: 'Tất cả trạng thái', + }, + status: { + completed: 'Hoàn thành', + failed: 'Thất bại', + running: 'Đang chạy', + queued: 'Trong hàng đợi', + cancelled: 'Đã hủy', + ignored: 'Đã bỏ qua', + }, + // prettier-ignore + kind: { + agent: 'Tác nhân', + pipeline: 'Pipeline', + processor: 'Bộ xử lý', + }, + columns: { + time: 'Thời gian', + target: 'Bộ xử lý', + status: 'Trạng thái', + duration: 'Thời lượng', + tokens: 'Token', + }, + debug: 'Gỡ lỗi', + empty: 'Không có lượt thực thi trong khoảng này', + loading: 'Đang tải lượt thực thi...', + triggeredBy: 'Được kích hoạt bởi {{trigger}}', + cards: { + totalExecutions: 'Lượt thực thi', + bySource: 'Tác nhân {{agent}} · Pipeline {{pipeline}}', + successRate: 'Tỷ lệ thực thi thành công', + successRateHint: + 'Hoàn thành ÷ (hoàn thành + thất bại). Không tính sự kiện bị bỏ qua và lượt chưa kết thúc vào mẫu số.', + denominator: + 'Thành công {{completed}} trong {{denominator}} lượt đã kết thúc', + running: 'Đang chạy', + queued: 'Trong hàng đợi', + waiting: 'Đang chờ nhập liệu', + failed: 'Thất bại', + ignored: 'Đã bỏ qua', + latency: 'Thời lượng P50 / P95', + p50: 'P50', + p95: 'P95', + sample: 'Mẫu gồm {{count}} lượt thực thi', + tokens: 'Token', + coverage: 'Có dữ liệu sử dụng cho {{withUsage}}/{{calls}} lệnh gọi', + hiddenDebug: 'Đã ẩn {{count}} lượt gỡ lỗi', + }, + detail: { + title: 'Lượt thực thi', + timeline: 'Dòng thời gian', + executionId: 'ID thực thi', + eventId: 'Sự kiện', + queue: 'Hàng đợi', + runner: 'Trình thực thi', + created: 'Được tạo', + duration: 'Thời lượng', + usage: 'Mức sử dụng', + noEvents: 'Chưa ghi nhận sự kiện truy vết', + query: 'Tin nhắn đầu vào', + modelCalls: 'Lệnh gọi mô hình', + toolCalls: 'Lệnh gọi công cụ', + errors: 'Lỗi', + loadError: 'Không thể tải truy vết thực thi', + openObject: 'Mở đối tượng', + a11yDescription: 'Toàn bộ truy vết của lượt thực thi này', + }, + }, title: 'Bảng điều khiển', description: 'Giám sát hoạt động Bot, cuộc gọi LLM và hiệu suất hệ thống', overview: 'Tổng quan', diff --git a/web/src/i18n/locales/zh-Hans.ts b/web/src/i18n/locales/zh-Hans.ts index 415e0ac21..274756a5e 100644 --- a/web/src/i18n/locales/zh-Hans.ts +++ b/web/src/i18n/locales/zh-Hans.ts @@ -2332,7 +2332,12 @@ const zhHans = { cancelled: '已取消', ignored: '已忽略', }, - kind: { agent: 'Agent', pipeline: 'Pipeline', processor: '处理器' }, + // prettier-ignore + kind: { + agent: 'Agent', + pipeline: 'Pipeline', + processor: '处理器', + }, columns: { time: '时间', target: '处理器', diff --git a/web/src/i18n/locales/zh-Hant.ts b/web/src/i18n/locales/zh-Hant.ts index 9aba8b01a..47bd4b684 100644 --- a/web/src/i18n/locales/zh-Hant.ts +++ b/web/src/i18n/locales/zh-Hant.ts @@ -2333,7 +2333,12 @@ const zhHant = { cancelled: '已取消', ignored: '已忽略', }, - kind: { agent: 'Agent', pipeline: 'Pipeline', processor: '處理器' }, + // prettier-ignore + kind: { + agent: 'Agent', + pipeline: 'Pipeline', + processor: '處理器', + }, columns: { time: '時間', target: '處理器', diff --git a/web/tests/e2e/fixtures/langbot-api.ts b/web/tests/e2e/fixtures/langbot-api.ts index a37925e17..19073a9c6 100644 --- a/web/tests/e2e/fixtures/langbot-api.ts +++ b/web/tests/e2e/fixtures/langbot-api.ts @@ -270,7 +270,9 @@ function executionText(raw: unknown): string { /** Derive the unified execution list from a mocked monitoring payload. */ function buildExecutionList(monitoringData: unknown) { - const payload = monitoringData as { messages?: RawMonitoringMessage[] } | undefined; + const payload = monitoringData as + | { messages?: RawMonitoringMessage[] } + | undefined; const items = (payload?.messages ?? []) .filter((message) => message.role !== 'assistant') .map((message) => { @@ -331,7 +333,9 @@ function buildExecutionList(monitoringData: unknown) { ignored: byStatus.ignored ?? 0, waiting: 0, success_rate: - denominator > 0 ? Math.round((completed / denominator) * 10000) / 100 : null, + denominator > 0 + ? Math.round((completed / denominator) * 10000) / 100 + : null, denominator, p50_duration_ms: null, p95_duration_ms: null, @@ -1308,12 +1312,13 @@ async function handleBackendApi(route: Route, state: LangBotApiMockState) { (rows ?? []).filter((row) => row.message_id === executionId); return fulfillJson(route, { source: 'pipeline', - message: - (payload.messages ?? []).find((row) => row.id === executionId) ?? { - id: executionId, - status: 'success', - message_content: '', - }, + message: (payload.messages ?? []).find( + (row) => row.id === executionId, + ) ?? { + id: executionId, + status: 'success', + message_content: '', + }, llm_calls: relatedToExecution(payload.llmCalls), tool_calls: relatedToExecution(payload.toolCalls), errors: relatedToExecution(payload.errors), diff --git a/web/tests/e2e/login.spec.ts b/web/tests/e2e/login.spec.ts index 11ae6108f..e60c78574 100644 --- a/web/tests/e2e/login.spec.ts +++ b/web/tests/e2e/login.spec.ts @@ -20,7 +20,7 @@ test('local account login reaches the authenticated home shell', async ({ await expect(page).toHaveURL(/\/home(?:\/monitoring)?$/); await expect(page.getByText('Home').first()).toBeVisible(); await expect(page.getByRole('button', { name: 'Dashboard' })).toBeVisible(); - await expect(page.getByText('Total Messages').first()).toBeVisible(); + await expect(page.getByText('Execution Success Rate').first()).toBeVisible(); await expect(page.getByText('Unable to connect to server')).toHaveCount(0); });