Skip to content

Commit 9cf4681

Browse files
author
Vamil Gandhi
committed
Group identical console messages in list_console_messages
1 parent 5cedcaa commit 9cf4681

2 files changed

Lines changed: 105 additions & 1 deletion

File tree

src/McpResponse.ts

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,51 @@ interface TraceInsightData {
3636
insightName: InsightName;
3737
}
3838

39+
class GroupedConsoleMessage {
40+
readonly key: string;
41+
#first: ConsoleFormatter;
42+
#count = 0;
43+
#msgids: number[] = [];
44+
45+
constructor(first: ConsoleFormatter) {
46+
this.#first = first;
47+
this.key = GroupedConsoleMessage.keyFor(first);
48+
this.add(first);
49+
}
50+
51+
static keyFor(message: ConsoleFormatter): string {
52+
const json = message.toJSON();
53+
return JSON.stringify({
54+
type: json.type,
55+
text: json.text,
56+
argsCount: json.argsCount,
57+
});
58+
}
59+
60+
add(message: ConsoleFormatter): void {
61+
const json = message.toJSON();
62+
this.#count++;
63+
this.#msgids.push(json.id);
64+
}
65+
66+
toString(): string {
67+
const base = this.#first.toString();
68+
if (this.#count <= 1) {
69+
return base;
70+
}
71+
return `${base} [${this.#count} times]`;
72+
}
73+
74+
toJSON(): object {
75+
const base = this.#first.toJSON();
76+
return {
77+
...base,
78+
count: this.#count,
79+
msgids: this.#msgids,
80+
};
81+
}
82+
}
83+
3984
export class McpResponse implements Response {
4085
#includePages = false;
4186
#snapshotParams?: SnapshotParams;
@@ -612,7 +657,7 @@ Call ${handleDialog.name} to handle it before continuing.`);
612657
}
613658

614659
if (this.#consoleDataOptions?.include) {
615-
const messages = data.consoleMessages ?? [];
660+
const messages = this.#groupConsoleMessages(data.consoleMessages ?? []);
616661

617662
response.push('## Console messages');
618663
if (messages.length) {
@@ -650,6 +695,41 @@ Call ${handleDialog.name} to handle it before continuing.`);
650695
};
651696
}
652697

698+
#groupConsoleMessages(
699+
messages: Array<ConsoleFormatter | IssueFormatter>,
700+
): Array<ConsoleFormatter | IssueFormatter | GroupedConsoleMessage> {
701+
const result: Array<ConsoleFormatter | IssueFormatter | GroupedConsoleMessage> = [];
702+
703+
let activeGroup: GroupedConsoleMessage | null = null;
704+
705+
const flush = () => {
706+
if (activeGroup) {
707+
result.push(activeGroup);
708+
activeGroup = null;
709+
}
710+
};
711+
712+
for (const message of messages) {
713+
if (!(message instanceof ConsoleFormatter)) {
714+
flush();
715+
result.push(message);
716+
continue;
717+
}
718+
719+
const key = GroupedConsoleMessage.keyFor(message);
720+
if (activeGroup && activeGroup.key === key) {
721+
activeGroup.add(message);
722+
continue;
723+
}
724+
725+
flush();
726+
activeGroup = new GroupedConsoleMessage(message);
727+
}
728+
729+
flush();
730+
return result;
731+
}
732+
653733
#dataWithPagination<T>(data: T[], pagination?: PaginationOptions) {
654734
const response = [];
655735
const paginationResult = paginate<T>(data, pagination);

tests/tools/console.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,30 @@ describe('console', () => {
4242
});
4343
});
4444

45+
it('groups identical messages', async () => {
46+
await withMcpContext(async (response, context) => {
47+
const page = await context.newPage();
48+
await page.setContent(`
49+
<script>
50+
for (let i = 0; i < 5; i++) {
51+
console.log('spam');
52+
}
53+
</script>
54+
`);
55+
await listConsoleMessages.handler({params: {}}, response, context);
56+
const formattedResponse = await response.handle('test', context);
57+
const textContent = getTextContent(formattedResponse.content[0]);
58+
assert.ok(
59+
textContent.includes('msgid=1 [log] spam (1 args) [5 times]'),
60+
textContent,
61+
);
62+
assert.ok(
63+
!textContent.includes('msgid=2 [log] spam'),
64+
'Should collapse subsequent identical messages',
65+
);
66+
});
67+
});
68+
4569
it('lists error objects', async t => {
4670
await withMcpContext(async (response, context) => {
4771
const page = await context.newPage();

0 commit comments

Comments
 (0)