mirror of
https://github.com/ChromeDevTools/chrome-devtools-mcp.git
synced 2026-09-14 19:45:30 +08:00
refactor: Merge MCP tools for comparing heap snapshots (#2281)
Instead of two separate MCP tools, we can have one instead which takes classIndex as optional argument. Co-authored-by: Dominik Inführ <dinfuehr@chromium.org>
This commit is contained in:
@@ -514,11 +514,10 @@ If you run into any issues, checkout our [troubleshooting guide](./docs/troubles
|
||||
- [`take_snapshot`](docs/tool-reference.md#take_snapshot)
|
||||
- [`screencast_start`](docs/tool-reference.md#screencast_start)
|
||||
- [`screencast_stop`](docs/tool-reference.md#screencast_stop)
|
||||
- **Memory** (11 tools)
|
||||
- **Memory** (10 tools)
|
||||
- [`take_heapsnapshot`](docs/tool-reference.md#take_heapsnapshot)
|
||||
- [`close_heapsnapshot`](docs/tool-reference.md#close_heapsnapshot)
|
||||
- [`compare_heapsnapshots_class_nodes`](docs/tool-reference.md#compare_heapsnapshots_class_nodes)
|
||||
- [`compare_heapsnapshots_summary`](docs/tool-reference.md#compare_heapsnapshots_summary)
|
||||
- [`compare_heapsnapshots`](docs/tool-reference.md#compare_heapsnapshots)
|
||||
- [`get_heapsnapshot_class_nodes`](docs/tool-reference.md#get_heapsnapshot_class_nodes)
|
||||
- [`get_heapsnapshot_details`](docs/tool-reference.md#get_heapsnapshot_details)
|
||||
- [`get_heapsnapshot_dominators`](docs/tool-reference.md#get_heapsnapshot_dominators)
|
||||
|
||||
+5
-17
@@ -39,11 +39,10 @@
|
||||
- [`take_snapshot`](#take_snapshot)
|
||||
- [`screencast_start`](#screencast_start)
|
||||
- [`screencast_stop`](#screencast_stop)
|
||||
- **[Memory](#memory)** (11 tools)
|
||||
- **[Memory](#memory)** (10 tools)
|
||||
- [`take_heapsnapshot`](#take_heapsnapshot)
|
||||
- [`close_heapsnapshot`](#close_heapsnapshot)
|
||||
- [`compare_heapsnapshots_class_nodes`](#compare_heapsnapshots_class_nodes)
|
||||
- [`compare_heapsnapshots_summary`](#compare_heapsnapshots_summary)
|
||||
- [`compare_heapsnapshots`](#compare_heapsnapshots)
|
||||
- [`get_heapsnapshot_class_nodes`](#get_heapsnapshot_class_nodes)
|
||||
- [`get_heapsnapshot_details`](#get_heapsnapshot_details)
|
||||
- [`get_heapsnapshot_dominators`](#get_heapsnapshot_dominators)
|
||||
@@ -464,26 +463,15 @@ in the DevTools Elements panel (if any).
|
||||
|
||||
---
|
||||
|
||||
### `compare_heapsnapshots_class_nodes`
|
||||
### `compare_heapsnapshots`
|
||||
|
||||
**Description:** Loads two memory heapsnapshots and returns the diff details (added/deleted instances) for a specific class. (requires flag: --memoryDebugging=true)
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- **baseFilePath** (string) **(required)**: A path to the base .heapsnapshot file (earlier snapshot).
|
||||
- **classIndex** (number) **(required)**: 0-based index of the class in the summary list to filter results, showing individual objects.
|
||||
- **currentFilePath** (string) **(required)**: A path to the current .heapsnapshot file (later snapshot).
|
||||
|
||||
---
|
||||
|
||||
### `compare_heapsnapshots_summary`
|
||||
|
||||
**Description:** Loads two memory heapsnapshots and returns the summary diff between them (classes with changes). (requires flag: --memoryDebugging=true)
|
||||
**Description:** Loads two memory heapsnapshots and returns the comparison. If classIndex is provided, returns detailed diff for that class, otherwise returns summary diff. (requires flag: --memoryDebugging=true)
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- **baseFilePath** (string) **(required)**: A path to the base .heapsnapshot file (earlier snapshot).
|
||||
- **currentFilePath** (string) **(required)**: A path to the current .heapsnapshot file (later snapshot).
|
||||
- **classIndex** (number) _(optional)_: Optional 0-based index of the class in the summary list to filter results, showing individual objects.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -108,9 +108,9 @@ export const commands: Commands = {
|
||||
},
|
||||
},
|
||||
},
|
||||
compare_heapsnapshots_class_nodes: {
|
||||
compare_heapsnapshots: {
|
||||
description:
|
||||
'Loads two memory heapsnapshots and returns the diff details (added/deleted instances) for a specific class. (requires flag: --memoryDebugging=true)',
|
||||
'Loads two memory heapsnapshots and returns the comparison. If classIndex is provided, returns detailed diff for that class, otherwise returns summary diff. (requires flag: --memoryDebugging=true)',
|
||||
category: 'Memory',
|
||||
args: {
|
||||
baseFilePath: {
|
||||
@@ -131,29 +131,8 @@ export const commands: Commands = {
|
||||
name: 'classIndex',
|
||||
type: 'number',
|
||||
description:
|
||||
'0-based index of the class in the summary list to filter results, showing individual objects.',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
compare_heapsnapshots_summary: {
|
||||
description:
|
||||
'Loads two memory heapsnapshots and returns the summary diff between them (classes with changes). (requires flag: --memoryDebugging=true)',
|
||||
category: 'Memory',
|
||||
args: {
|
||||
baseFilePath: {
|
||||
name: 'baseFilePath',
|
||||
type: 'string',
|
||||
description:
|
||||
'A path to the base .heapsnapshot file (earlier snapshot).',
|
||||
required: true,
|
||||
},
|
||||
currentFilePath: {
|
||||
name: 'currentFilePath',
|
||||
type: 'string',
|
||||
description:
|
||||
'A path to the current .heapsnapshot file (later snapshot).',
|
||||
required: true,
|
||||
'Optional 0-based index of the class in the summary list to filter results, showing individual objects.',
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -826,7 +826,8 @@
|
||||
"name": "class_index",
|
||||
"argType": "number"
|
||||
}
|
||||
]
|
||||
],
|
||||
"isDeprecated": true
|
||||
},
|
||||
{
|
||||
"name": "compare_heapsnapshots_summary",
|
||||
@@ -839,6 +840,24 @@
|
||||
"name": "current_file_path_length",
|
||||
"argType": "number"
|
||||
}
|
||||
],
|
||||
"isDeprecated": true
|
||||
},
|
||||
{
|
||||
"name": "compare_heapsnapshots",
|
||||
"args": [
|
||||
{
|
||||
"name": "base_file_path_length",
|
||||
"argType": "number"
|
||||
},
|
||||
{
|
||||
"name": "current_file_path_length",
|
||||
"argType": "number"
|
||||
},
|
||||
{
|
||||
"name": "class_index",
|
||||
"argType": "number"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
+19
-39
@@ -281,39 +281,10 @@ export const getHeapSnapshotDominators = defineTool({
|
||||
},
|
||||
});
|
||||
|
||||
export const compareHeapSnapshotsSummary = defineTool({
|
||||
name: 'compare_heapsnapshots_summary',
|
||||
export const compareHeapSnapshots = defineTool({
|
||||
name: 'compare_heapsnapshots',
|
||||
description:
|
||||
'Loads two memory heapsnapshots and returns the summary diff between them (classes with changes).',
|
||||
annotations: {
|
||||
category: ToolCategory.MEMORY,
|
||||
readOnlyHint: true,
|
||||
conditions: ['memoryDebugging'],
|
||||
},
|
||||
verifyFilesSchema: ['baseFilePath', 'currentFilePath'],
|
||||
schema: {
|
||||
baseFilePath: zod
|
||||
.string()
|
||||
.describe('A path to the base .heapsnapshot file (earlier snapshot).'),
|
||||
currentFilePath: zod
|
||||
.string()
|
||||
.describe('A path to the current .heapsnapshot file (later snapshot).'),
|
||||
},
|
||||
blockedByDialog: false,
|
||||
handler: async (request, response, context) => {
|
||||
const diff = await context.getHeapSnapshotClassDiffs(
|
||||
request.params.baseFilePath,
|
||||
request.params.currentFilePath,
|
||||
);
|
||||
|
||||
response.setHeapSnapshotClassDiffs(diff);
|
||||
},
|
||||
});
|
||||
|
||||
export const compareHeapSnapshotsClassNodes = defineTool({
|
||||
name: 'compare_heapsnapshots_class_nodes',
|
||||
description:
|
||||
'Loads two memory heapsnapshots and returns the diff details (added/deleted instances) for a specific class.',
|
||||
'Loads two memory heapsnapshots and returns the comparison. If classIndex is provided, returns detailed diff for that class, otherwise returns summary diff.',
|
||||
annotations: {
|
||||
category: ToolCategory.MEMORY,
|
||||
readOnlyHint: true,
|
||||
@@ -329,17 +300,26 @@ export const compareHeapSnapshotsClassNodes = defineTool({
|
||||
.describe('A path to the current .heapsnapshot file (later snapshot).'),
|
||||
classIndex: zod
|
||||
.number()
|
||||
.optional()
|
||||
.describe(
|
||||
'0-based index of the class in the summary list to filter results, showing individual objects.',
|
||||
'Optional 0-based index of the class in the summary list to filter results, showing individual objects.',
|
||||
),
|
||||
},
|
||||
blockedByDialog: false,
|
||||
handler: async (request, response, context) => {
|
||||
const classDiffResult = await context.getHeapSnapshotDetailedClassDiff(
|
||||
request.params.baseFilePath,
|
||||
request.params.currentFilePath,
|
||||
request.params.classIndex,
|
||||
);
|
||||
response.setHeapSnapshotDetailedClassDiff(classDiffResult);
|
||||
if (request.params.classIndex !== undefined) {
|
||||
const classDiffResult = await context.getHeapSnapshotDetailedClassDiff(
|
||||
request.params.baseFilePath,
|
||||
request.params.currentFilePath,
|
||||
request.params.classIndex,
|
||||
);
|
||||
response.setHeapSnapshotDetailedClassDiff(classDiffResult);
|
||||
} else {
|
||||
const diff = await context.getHeapSnapshotClassDiffs(
|
||||
request.params.baseFilePath,
|
||||
request.params.currentFilePath,
|
||||
);
|
||||
response.setHeapSnapshotClassDiffs(diff);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
exports[`memory > compare_heapsnapshots_class_nodes > compare heap-1 to heap-2 with classIndex filter 1`] = `
|
||||
## Heap Snapshot Data
|
||||
### Heap Snapshot Detailed Diff
|
||||
NewObject: # new: 2, # deleted: 0, # delta: +2, alloc size: +0.1 kB, freed size: 0.0 kB, size delta: +0.1 kB
|
||||
Objects:
|
||||
+ @35179 (self_size: 0.1 kB)
|
||||
+ @35181 (self_size: 0.1 kB)
|
||||
`;
|
||||
|
||||
exports[`memory > compare_heapsnapshots_summary > compare heap-1 to heap-2 1`] = `
|
||||
exports[`memory > compare_heapsnapshots > compare heap-1 to heap-2 1`] = `
|
||||
## Heap Snapshot Data
|
||||
### Heap Snapshot Diff
|
||||
index,className,addedCount,removedCount,countDelta,addedSize,removedSize,sizeDelta
|
||||
@@ -23,7 +14,16 @@ index,className,addedCount,removedCount,countDelta,addedSize,removedSize,sizeDel
|
||||
9,InitialObject,0,2,-2,0.0 kB,0.1 kB,-0.1 kB
|
||||
`;
|
||||
|
||||
exports[`memory > compare_heapsnapshots_summary > compare heap-2 to heap-3 1`] = `
|
||||
exports[`memory > compare_heapsnapshots > compare heap-1 to heap-2 with classIndex filter 1`] = `
|
||||
## Heap Snapshot Data
|
||||
### Heap Snapshot Detailed Diff
|
||||
NewObject: # new: 2, # deleted: 0, # delta: +2, alloc size: +0.1 kB, freed size: 0.0 kB, size delta: +0.1 kB
|
||||
Objects:
|
||||
+ @35179 (self_size: 0.1 kB)
|
||||
+ @35181 (self_size: 0.1 kB)
|
||||
`;
|
||||
|
||||
exports[`memory > compare_heapsnapshots > compare heap-2 to heap-3 1`] = `
|
||||
## Heap Snapshot Data
|
||||
### Heap Snapshot Diff
|
||||
index,className,addedCount,removedCount,countDelta,addedSize,removedSize,sizeDelta
|
||||
|
||||
+11
-14
@@ -21,8 +21,7 @@ import {
|
||||
getHeapSnapshotRetainingPaths,
|
||||
getHeapSnapshotEdges,
|
||||
getHeapSnapshotDominators,
|
||||
compareHeapSnapshotsSummary,
|
||||
compareHeapSnapshotsClassNodes,
|
||||
compareHeapSnapshots,
|
||||
} from '../../src/tools/memory.js';
|
||||
import {withMcpContext} from '../utils.js';
|
||||
|
||||
@@ -364,7 +363,7 @@ describe('memory', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('compare_heapsnapshots_summary', () => {
|
||||
describe('compare_heapsnapshots', () => {
|
||||
it('compare heap-1 to heap-2', async t => {
|
||||
await withMcpContext(async (response, context) => {
|
||||
const filePathA = join(
|
||||
@@ -376,14 +375,14 @@ describe('memory', () => {
|
||||
'tests/fixtures/heap-2.heapsnapshot',
|
||||
);
|
||||
|
||||
await compareHeapSnapshotsSummary.handler(
|
||||
await compareHeapSnapshots.handler(
|
||||
{params: {baseFilePath: filePathA, currentFilePath: filePathB}},
|
||||
response,
|
||||
context,
|
||||
);
|
||||
|
||||
const responseData = await response.handle(
|
||||
compareHeapSnapshotsSummary.name,
|
||||
compareHeapSnapshots.name,
|
||||
context,
|
||||
);
|
||||
const output = responseData.content
|
||||
@@ -405,14 +404,14 @@ describe('memory', () => {
|
||||
'tests/fixtures/heap-3.heapsnapshot',
|
||||
);
|
||||
|
||||
await compareHeapSnapshotsSummary.handler(
|
||||
await compareHeapSnapshots.handler(
|
||||
{params: {baseFilePath: filePathA, currentFilePath: filePathB}},
|
||||
response,
|
||||
context,
|
||||
);
|
||||
|
||||
const responseData = await response.handle(
|
||||
compareHeapSnapshotsSummary.name,
|
||||
compareHeapSnapshots.name,
|
||||
context,
|
||||
);
|
||||
const output = responseData.content
|
||||
@@ -422,9 +421,7 @@ describe('memory', () => {
|
||||
t.assert.snapshot(output);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('compare_heapsnapshots_class_nodes', () => {
|
||||
it('compare heap-1 to heap-2 with classIndex filter', async t => {
|
||||
await withMcpContext(async (response, context) => {
|
||||
const filePathA = join(
|
||||
@@ -436,7 +433,7 @@ describe('memory', () => {
|
||||
'tests/fixtures/heap-2.heapsnapshot',
|
||||
);
|
||||
|
||||
await compareHeapSnapshotsClassNodes.handler(
|
||||
await compareHeapSnapshots.handler(
|
||||
{
|
||||
params: {
|
||||
baseFilePath: filePathA,
|
||||
@@ -449,7 +446,7 @@ describe('memory', () => {
|
||||
);
|
||||
|
||||
const responseData = await response.handle(
|
||||
compareHeapSnapshotsClassNodes.name,
|
||||
compareHeapSnapshots.name,
|
||||
context,
|
||||
);
|
||||
const output = responseData.content
|
||||
@@ -460,7 +457,7 @@ describe('memory', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('compare heap-1 to heap-2 with invalid classIndex throws error', async t => {
|
||||
it('compare heap-1 to heap-2 with invalid classIndex throws error', async () => {
|
||||
await withMcpContext(async (response, context) => {
|
||||
const filePathA = join(
|
||||
process.cwd(),
|
||||
@@ -471,8 +468,8 @@ describe('memory', () => {
|
||||
'tests/fixtures/heap-2.heapsnapshot',
|
||||
);
|
||||
|
||||
await t.assert.rejects(
|
||||
compareHeapSnapshotsClassNodes.handler(
|
||||
await assert.rejects(
|
||||
compareHeapSnapshots.handler(
|
||||
{
|
||||
params: {
|
||||
baseFilePath: filePathA,
|
||||
|
||||
Reference in New Issue
Block a user