mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-20 17:30:59 +00:00
196 lines
4.9 KiB
TypeScript
196 lines
4.9 KiB
TypeScript
import { expect, test } from '@playwright/test';
|
|
|
|
import { installLangBotApiMocks } from './fixtures/langbot-api';
|
|
|
|
const bot = {
|
|
id: 'bot-pipeline-monitoring',
|
|
name: 'Pipeline Bot',
|
|
};
|
|
|
|
const pipeline = {
|
|
id: 'pipeline-monitoring',
|
|
name: 'Pipeline Under Test',
|
|
};
|
|
|
|
function at(minute: number) {
|
|
return `2026-07-02T10:${String(minute).padStart(2, '0')}:00Z`;
|
|
}
|
|
|
|
function message(
|
|
id: string,
|
|
role: 'user' | 'assistant',
|
|
minute: number,
|
|
content: string,
|
|
sessionId = 'session-pipeline-agent',
|
|
) {
|
|
return {
|
|
id,
|
|
timestamp: at(minute),
|
|
bot_id: bot.id,
|
|
bot_name: bot.name,
|
|
pipeline_id: pipeline.id,
|
|
pipeline_name: pipeline.name,
|
|
message_content: content,
|
|
session_id: sessionId,
|
|
status: 'success',
|
|
level: 'info',
|
|
platform: role === 'user' ? 'person' : 'bot',
|
|
user_id: 'pipeline-user',
|
|
user_name: 'Pipeline User',
|
|
runner_name: 'local-agent',
|
|
variables: '{}',
|
|
role,
|
|
};
|
|
}
|
|
|
|
function llmCall(
|
|
id: string,
|
|
minute: number,
|
|
messageId: string,
|
|
input: number,
|
|
output: number,
|
|
duration: number,
|
|
) {
|
|
return {
|
|
id,
|
|
timestamp: at(minute),
|
|
model_name: 'gpt-5.5',
|
|
input_tokens: input,
|
|
output_tokens: output,
|
|
total_tokens: input + output,
|
|
duration,
|
|
cost: 0,
|
|
status: 'success',
|
|
bot_id: bot.id,
|
|
bot_name: bot.name,
|
|
pipeline_id: pipeline.id,
|
|
pipeline_name: pipeline.name,
|
|
session_id: 'session-pipeline-agent',
|
|
message_id: messageId,
|
|
};
|
|
}
|
|
|
|
function toolCall(id: string, minute: number, messageId: string, name: string) {
|
|
return {
|
|
id,
|
|
timestamp: at(minute),
|
|
tool_name: name,
|
|
tool_source: 'native',
|
|
duration: 120,
|
|
status: 'success',
|
|
bot_id: bot.id,
|
|
bot_name: bot.name,
|
|
pipeline_id: pipeline.id,
|
|
pipeline_name: pipeline.name,
|
|
session_id: 'session-pipeline-agent',
|
|
message_id: messageId,
|
|
arguments: JSON.stringify({ query: name }),
|
|
result: JSON.stringify({ ok: true }),
|
|
};
|
|
}
|
|
|
|
function monitoringData() {
|
|
const messages = [
|
|
message(
|
|
'single-user',
|
|
'user',
|
|
1,
|
|
'Pipeline single user message without reply',
|
|
'session-pipeline-single',
|
|
),
|
|
message('agent-user', 'user', 10, 'Pipeline needs a deployment plan'),
|
|
message(
|
|
'agent-assistant-1',
|
|
'assistant',
|
|
11,
|
|
'Pipeline agent step 1: inspect repository',
|
|
),
|
|
message(
|
|
'agent-assistant-2',
|
|
'assistant',
|
|
12,
|
|
'Pipeline agent step 2: run tests',
|
|
),
|
|
message(
|
|
'agent-assistant-3',
|
|
'assistant',
|
|
13,
|
|
'Pipeline final answer: deployment ready',
|
|
),
|
|
];
|
|
const llmCalls = [
|
|
llmCall('pipeline-call-1', 10, 'agent-user', 100, 40, 180),
|
|
llmCall('pipeline-call-2', 11, 'agent-user', 140, 50, 220),
|
|
];
|
|
const toolCalls = [
|
|
toolCall('pipeline-tool-1', 11, 'agent-user', 'repo_search'),
|
|
toolCall('pipeline-tool-2', 12, 'agent-user', 'run_tests'),
|
|
];
|
|
|
|
return {
|
|
overview: {
|
|
total_messages: messages.length,
|
|
llm_calls: llmCalls.length,
|
|
embedding_calls: 0,
|
|
model_calls: llmCalls.length,
|
|
success_rate: 100,
|
|
active_sessions: 2,
|
|
},
|
|
messages,
|
|
llmCalls,
|
|
toolCalls,
|
|
embeddingCalls: [],
|
|
sessions: [],
|
|
errors: [],
|
|
totalCount: {
|
|
messages: messages.length,
|
|
llmCalls: llmCalls.length,
|
|
toolCalls: toolCalls.length,
|
|
embeddingCalls: 0,
|
|
sessions: 0,
|
|
errors: 0,
|
|
},
|
|
};
|
|
}
|
|
|
|
test.describe('pipeline monitoring conversation turns', () => {
|
|
test('uses conversation turns and folded tool calls in the pipeline dashboard', async ({
|
|
page,
|
|
}) => {
|
|
await installLangBotApiMocks(page, {
|
|
authenticated: true,
|
|
monitoringData: monitoringData(),
|
|
});
|
|
|
|
await page.goto(`/home/pipelines?id=${pipeline.id}`);
|
|
await page.getByRole('tab', { name: 'Dashboard' }).click();
|
|
|
|
await expect(page.getByText('2 conversation turns')).toBeVisible();
|
|
await expect(
|
|
page.getByText('Pipeline single user message without reply'),
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByText('Pipeline needs a deployment plan'),
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByText('Pipeline agent step 1: inspect repository'),
|
|
).toBeVisible();
|
|
await expect(page.getByText('Assistant +2')).toBeVisible();
|
|
await expect(page.getByText('2 tools')).toBeVisible();
|
|
|
|
const agentTurn = page
|
|
.locator('div[role="button"]')
|
|
.filter({ hasText: 'Pipeline needs a deployment plan' });
|
|
await expect(agentTurn).toHaveCount(1);
|
|
await agentTurn.click();
|
|
|
|
await expect(page.getByText('Tool Calls (2)')).toBeVisible();
|
|
await expect(page.getByText('#1 repo_search')).toBeVisible();
|
|
await expect(page.getByText('#2 run_tests')).toBeVisible();
|
|
await expect(page.getByText('Arguments')).toHaveCount(0);
|
|
await page.getByText('#1 repo_search').click();
|
|
await expect(page.getByText('Arguments')).toBeVisible();
|
|
await expect(page.getByText('Result')).toBeVisible();
|
|
});
|
|
});
|