diff --git a/src/McpResponse.ts b/src/McpResponse.ts index 5826bed5..e9a9c59d 100644 --- a/src/McpResponse.ts +++ b/src/McpResponse.ts @@ -444,7 +444,6 @@ Call ${handleDialog.name} to handle it before continuing.`); return response; } - response.push(`## Console Message ${data.consoleMessageStableId}`); response.push(formatConsoleEventVerbose(data)); return response; } diff --git a/src/formatters/consoleFormatter.ts b/src/formatters/consoleFormatter.ts index 47ba47b3..22f54032 100644 --- a/src/formatters/consoleFormatter.ts +++ b/src/formatters/consoleFormatter.ts @@ -6,64 +6,49 @@ import type {ConsoleMessageData} from '../McpResponse.js'; -const logLevels: Record = { - log: 'Log', - info: 'Info', - warning: 'Warning', - error: 'Error', - exception: 'Exception', - assert: 'Assert', -}; - // The short format for a console message, based on a previous format. export function formatConsoleEventShort(msg: ConsoleMessageData): string { - const args = msg.args ? formatArgs(msg, false) : ''; - return `msgid=${msg.consoleMessageStableId} [${msg.type}] ${msg.message}${args}`; + return `msgid=${msg.consoleMessageStableId} [${msg.type}] ${msg.message} (${msg.args?.length ?? 0} args)`; } -// The verbose format for a console message, including all details. -export function formatConsoleEventVerbose(msg: ConsoleMessageData): string { - const logLevel = msg.type ? (logLevels[msg.type] ?? 'Log') : 'Log'; - let result = `${logLevel}> ${msg.message}`; +function getArgs(msg: ConsoleMessageData) { + const args = [...(msg.args ?? [])]; - if (msg.args && msg.args.length > 0) { - result += formatArgs(msg, true); + // If there is no text, the first argument serves as text (see formatMessage). + if (!msg.message) { + args.shift(); } - result += ` - ID: ${msg.consoleMessageStableId}`; - result += ` - Type: ${msg.type}`; + return args; +} + +// The verbose format for a console message, including all details. +export function formatConsoleEventVerbose(msg: ConsoleMessageData): string { + const result = [ + `ID: ${msg.consoleMessageStableId}`, + `Message: ${msg.type}> ${msg.message}`, + formatArgs(msg), + ]; + + return result.join('\n'); +} - return result; +function formatArg(arg: unknown) { + return typeof arg === 'object' ? JSON.stringify(arg) : String(arg); } -// If `includeAllArgs` is false, only includes the first arg and indicates that there are more args. -function formatArgs( - consoleData: ConsoleMessageData, - includeAllArgs = false, -): string { - if (!consoleData.args || consoleData.args.length === 0) { +function formatArgs(consoleData: ConsoleMessageData): string { + const args = getArgs(consoleData); + + if (!args.length) { return ''; } - let formattedArgs = ''; - // In the short format version, we only include the first arg. - const messageArgsToFormat = includeAllArgs - ? consoleData.args - : [consoleData.args[0]]; - - for (const arg of messageArgsToFormat) { - if (arg !== consoleData.message) { - formattedArgs += ' '; - formattedArgs += - typeof arg === 'object' ? JSON.stringify(arg) : String(arg); - } - } + const result = ['### Arguments']; - if (!includeAllArgs && consoleData.args.length > 1) { - formattedArgs += ` ...`; + for (const [key, arg] of args.entries()) { + result.push(`Arg #${key}: ${formatArg(arg)}`); } - return formattedArgs.length > 0 ? ` Args:${formattedArgs}` : ''; + return result.join('\n'); } diff --git a/tests/formatters/consoleFormatter.test.js.snapshot b/tests/formatters/consoleFormatter.test.js.snapshot new file mode 100644 index 00000000..473f9fa1 --- /dev/null +++ b/tests/formatters/consoleFormatter.test.js.snapshot @@ -0,0 +1,38 @@ +exports[`consoleFormatter > formatConsoleEventShort > formats a console.log message 1`] = ` +msgid=1 [log] Hello, world! (0 args) +`; + +exports[`consoleFormatter > formatConsoleEventShort > formats a console.log message with multiple arguments 1`] = ` +msgid=3 [log] Processing file: (2 args) +`; + +exports[`consoleFormatter > formatConsoleEventShort > formats a console.log message with one argument 1`] = ` +msgid=2 [log] Processing file: (1 args) +`; + +exports[`consoleFormatter > formatConsoleEventVerbose > formats a console.error message 1`] = ` +ID: 4 +Message: error> Something went wrong + +`; + +exports[`consoleFormatter > formatConsoleEventVerbose > formats a console.log message 1`] = ` +ID: 1 +Message: log> Hello, world! + +`; + +exports[`consoleFormatter > formatConsoleEventVerbose > formats a console.log message with multiple arguments 1`] = ` +ID: 3 +Message: log> Processing file: +### Arguments +Arg #0: file.txt +Arg #1: another file +`; + +exports[`consoleFormatter > formatConsoleEventVerbose > formats a console.log message with one argument 1`] = ` +ID: 2 +Message: log> Processing file: +### Arguments +Arg #0: file.txt +`; diff --git a/tests/formatters/consoleFormatter.test.ts b/tests/formatters/consoleFormatter.test.ts index d96ec196..a498d8f2 100644 --- a/tests/formatters/consoleFormatter.test.ts +++ b/tests/formatters/consoleFormatter.test.ts @@ -4,7 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -import assert from 'node:assert'; import {describe, it} from 'node:test'; import { @@ -15,7 +14,7 @@ import type {ConsoleMessageData} from '../../src/McpResponse.js'; describe('consoleFormatter', () => { describe('formatConsoleEventShort', () => { - it('formats a console.log message', () => { + it('formats a console.log message', t => { const message: ConsoleMessageData = { consoleMessageStableId: 1, type: 'log', @@ -23,10 +22,10 @@ describe('consoleFormatter', () => { args: [], }; const result = formatConsoleEventShort(message); - assert.equal(result, 'msgid=1 [log] Hello, world!'); + t.assert.snapshot?.(result); }); - it('formats a console.log message with one argument', () => { + it('formats a console.log message with one argument', t => { const message: ConsoleMessageData = { consoleMessageStableId: 2, type: 'log', @@ -34,10 +33,10 @@ describe('consoleFormatter', () => { args: ['file.txt'], }; const result = formatConsoleEventShort(message); - assert.equal(result, 'msgid=2 [log] Processing file: Args: file.txt'); + t.assert.snapshot?.(result); }); - it('formats a console.log message with multiple arguments', () => { + it('formats a console.log message with multiple arguments', t => { const message: ConsoleMessageData = { consoleMessageStableId: 3, type: 'log', @@ -45,23 +44,12 @@ describe('consoleFormatter', () => { args: ['file.txt', 'another file'], }; const result = formatConsoleEventShort(message); - assert.equal(result, 'msgid=3 [log] Processing file: Args: file.txt ...'); - }); - - it('does not include args if message is the same as arg', () => { - const message: ConsoleMessageData = { - consoleMessageStableId: 4, - type: 'log', - message: 'Hello', - args: ['Hello'], - }; - const result = formatConsoleEventShort(message); - assert.equal(result, 'msgid=4 [log] Hello'); + t.assert.snapshot?.(result); }); }); describe('formatConsoleEventVerbose', () => { - it('formats a console.log message', () => { + it('formats a console.log message', t => { const message: ConsoleMessageData = { consoleMessageStableId: 1, type: 'log', @@ -69,15 +57,10 @@ describe('consoleFormatter', () => { args: [], }; const result = formatConsoleEventVerbose(message); - assert.equal( - result, - `Log> Hello, world! - ID: 1 - Type: log`, - ); + t.assert.snapshot?.(result); }); - it('formats a console.log message with one argument', () => { + it('formats a console.log message with one argument', t => { const message: ConsoleMessageData = { consoleMessageStableId: 2, type: 'log', @@ -85,15 +68,10 @@ describe('consoleFormatter', () => { args: ['file.txt'], }; const result = formatConsoleEventVerbose(message); - assert.equal( - result, - `Log> Processing file: Args: file.txt - ID: 2 - Type: log`, - ); + t.assert.snapshot?.(result); }); - it('formats a console.log message with multiple arguments', () => { + it('formats a console.log message with multiple arguments', t => { const message: ConsoleMessageData = { consoleMessageStableId: 3, type: 'log', @@ -101,43 +79,17 @@ describe('consoleFormatter', () => { args: ['file.txt', 'another file'], }; const result = formatConsoleEventVerbose(message); - assert.equal( - result, - `Log> Processing file: Args: file.txt another file - ID: 3 - Type: log`, - ); + t.assert.snapshot?.(result); }); - it('formats a console.error message', () => { + it('formats a console.error message', t => { const message: ConsoleMessageData = { consoleMessageStableId: 4, type: 'error', message: 'Something went wrong', }; const result = formatConsoleEventVerbose(message); - assert.equal( - result, - `Error> Something went wrong - ID: 4 - Type: error`, - ); - }); - - it('does not include args if message is the same as arg', () => { - const message: ConsoleMessageData = { - consoleMessageStableId: 5, - type: 'log', - message: 'Hello', - args: ['Hello', 'World'], - }; - const result = formatConsoleEventVerbose(message); - assert.equal( - result, - `Log> Hello Args: World - ID: 5 - Type: log`, - ); + t.assert.snapshot?.(result); }); }); }); diff --git a/tests/tools/console.test.ts b/tests/tools/console.test.ts index a96b3644..bce88d55 100644 --- a/tests/tools/console.test.ts +++ b/tests/tools/console.test.ts @@ -58,10 +58,6 @@ describe('console', () => { const formattedResponse = response.format('test', context); const textContent = formattedResponse[0] as {text: string}; - assert.ok( - textContent.text.includes('## Console Message 1'), - 'Should contain console message title', - ); assert.ok( textContent.text.includes('msgid=1 [error] This is an error'), 'Should contain console message body',