getChangeset
Retrieve details of a WordPress code changeset or commit, including commit message, author, and diff. Specify a revision number to access specific changes in the WordPress development history.
Instructions
Get information about a specific WordPress code changeset/commit including commit message, author, and diff.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| diffLimit | No | Maximum characters of diff to return (default: 2000, max: 10000) | |
| includeDiff | No | Include diff content (default: true) | |
| revision | Yes | SVN revision number (e.g., 58504) |
Implementation Reference
- src/index.ts:521-620 (handler)Main handler for the 'getChangeset' tool. Fetches the changeset page from WordPress Trac, parses HTML to extract author, date, commit message, changed files, and optionally the diff (truncated if large). Returns structured result with metadata.case "getChangeset": { const { revision, includeDiff = true, diffLimit = 2000 } = args; try { const changesetUrl = `https://core.trac.wordpress.org/changeset/${revision}`; // Fetch changeset page const response = await fetch(changesetUrl, { headers: { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } }); if (!response.ok) { throw new Error(`Changeset ${revision} not found`); } const html = await response.text(); // Parse changeset information from HTML with improved patterns const messageMatch = html.match(/<dd class="message[^"]*"[^>]*>\s*<p[^>]*>(.*?)<\/p>/s) || html.match(/<dd class="message[^"]*"[^>]*>(.*?)<\/dd>/s) || html.match(/<div class="message"[^>]*>\s*<p[^>]*>(.*?)<\/p>/s) || html.match(/<div class="message"[^>]*>(.*?)<\/div>/s); const authorMatch = html.match(/<dd class="author"[^>]*><span class="trac-author"[^>]*>(.*?)<\/span><\/dd>/s) || html.match(/<dt class="property author">Author:<\/dt>\s*<dd class="author">(.*?)<\/dd>/s) || html.match(/<dt>Author:<\/dt>\s*<dd>(.*?)<\/dd>/s); const dateMatch = html.match(/<dd class="date"[^>]*>(.*?)<\/dd>/s) || html.match(/<dt class="property date">Date:<\/dt>\s*<dd class="date">(.*?)<\/dd>/s) || html.match(/<dt>Date:<\/dt>\s*<dd>(.*?)<\/dd>/s); const changeset = { revision, author: authorMatch?.[1] ? authorMatch[1].replace(/<[^>]*>/g, '').trim() : '', date: dateMatch?.[1] ? dateMatch[1].replace(/<[^>]*>/g, '').trim() : '', message: messageMatch?.[1] ? messageMatch[1].replace(/<[^>]*>/g, '').trim() : '', files: [] as string[], diff: '', }; // Extract file list with improved patterns const fileMatches = html.match(/<h2[^>]*>Files:<\/h2>([\s\S]*?)<\/div>/) || html.match(/<div class="files"[^>]*>([\s\S]*?)<\/div>/) || html.match(/<div[^>]*class="[^"]*files[^"]*"[^>]*>([\s\S]*?)<\/div>/); if (fileMatches?.[1]) { const fileListHtml = fileMatches[1]; const filePathMatches = fileListHtml.match(/<a[^>]*href="[^"]*\/browser\/[^"]*"[^>]*>(.*?)<\/a>/g) || fileListHtml.match(/<a[^>]*href="[^"]*"[^>]*>(.*?)<\/a>/g) || fileListHtml.match(/<li[^>]*>(.*?)<\/li>/g); if (filePathMatches) { changeset.files = filePathMatches .map(match => match.replace(/<[^>]*>/g, '').trim()) .filter(path => path && !path.includes('(') && !path.includes('modified') && !path.includes('added') && !path.includes('deleted')) .slice(0, 20); // Limit to first 20 files } } // Get diff if requested if (includeDiff) { try { const diffUrl = `${changesetUrl}?format=diff`; const diffResponse = await fetch(diffUrl, { headers: { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } }); if (diffResponse.ok) { let diffText = await diffResponse.text(); const maxDiffLength = Math.min(diffLimit, 10000); if (diffText.length > maxDiffLength) { diffText = diffText.substring(0, maxDiffLength) + '\n... [diff truncated] ...'; } changeset.diff = diffText; } } catch (error) { console.warn('Failed to load diff:', error); } } result = { id: revision.toString(), title: `r${revision}: ${changeset.message}`, text: `Changeset r${revision}\nAuthor: ${changeset.author}\nDate: ${changeset.date}\n\nMessage:\n${changeset.message}\n\nFiles changed: ${changeset.files.length}\n${changeset.files.slice(0, 10).join('\n')}${changeset.files.length > 10 ? '\n...' : ''}\n\n${changeset.diff ? `Diff:\n${changeset.diff}` : 'No diff available'}`, url: changesetUrl, metadata: { changeset, totalFiles: changeset.files.length, }, }; } catch (error) { result = { id: revision.toString(), title: `Error loading changeset ${revision}`, text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`, url: `https://core.trac.wordpress.org/changeset/${revision}`, metadata: { error: true }, }; } break;
- src/index.ts:99-118 (schema)Input schema for the getChangeset tool defining parameters: revision (required number), includeDiff (boolean, default true), diffLimit (number, default 2000).inputSchema: { type: "object", properties: { revision: { type: "number", description: "SVN revision number (e.g., 58504)", }, includeDiff: { type: "boolean", description: "Include diff content (default: true)", default: true, }, diffLimit: { type: "number", description: "Maximum characters of diff to return (default: 2000, max: 10000)", default: 2000, }, }, required: ["revision"], },
- src/index.ts:96-119 (registration)Registration of the getChangeset tool in the tools/list endpoint response, including name, description, and input schema.{ name: "getChangeset", description: "Get information about a specific WordPress code changeset/commit including commit message, author, and diff.", inputSchema: { type: "object", properties: { revision: { type: "number", description: "SVN revision number (e.g., 58504)", }, includeDiff: { type: "boolean", description: "Include diff content (default: true)", default: true, }, diffLimit: { type: "number", description: "Maximum characters of diff to return (default: 2000, max: 10000)", default: 2000, }, }, required: ["revision"], }, },
- src/index.ts:1224-1299 (helper)Helper function getChangesetForChatGPT that implements similar changeset fetching and parsing logic tailored for ChatGPT's search/fetch tools, including caching.async function getChangesetForChatGPT(revision: number, includeDiff: boolean) { try { const changesetUrl = `https://core.trac.wordpress.org/changeset/${revision}`; const response = await fetch(changesetUrl, { headers: { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } }); if (!response.ok) { throw new Error(`Changeset ${revision} not found`); } const html = await response.text(); const messageMatch = html.match(/<dd class="message[^"]*"[^>]*>\s*<p[^>]*>(.*?)<\/p>/s) || html.match(/<dd class="message[^"]*"[^>]*>(.*?)<\/dd>/s); const authorMatch = html.match(/<dd class="author"[^>]*><span class="trac-author"[^>]*>(.*?)<\/span><\/dd>/s) || html.match(/<dt class="property author">Author:<\/dt>\s*<dd class="author">(.*?)<\/dd>/s); const dateMatch = html.match(/<dd class="date"[^>]*>(.*?)<\/dd>/s) || html.match(/<dt class="property date">Date:<\/dt>\s*<dd class="date">(.*?)<\/dd>/s); const changeset = { revision, author: authorMatch?.[1] ? authorMatch[1].replace(/<[^>]*>/g, '').trim() : '', date: dateMatch?.[1] ? dateMatch[1].replace(/<[^>]*>/g, '').trim() : '', message: messageMatch?.[1] ? messageMatch[1].replace(/<[^>]*>/g, '').trim() : '', diff: '', }; // Get diff if requested if (includeDiff) { try { const diffUrl = `${changesetUrl}?format=diff`; const diffResponse = await fetch(diffUrl, { headers: { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } }); if (diffResponse.ok) { let diffText = await diffResponse.text(); const maxDiffLength = 2000; if (diffText.length > maxDiffLength) { diffText = diffText.substring(0, maxDiffLength) + '\n... [diff truncated] ...'; } changeset.diff = diffText; } } catch (error) { console.warn('Failed to load diff:', error); } } // Cache the changeset chatgptCache.set(`r${revision}`, changeset); const diffText = changeset.diff ? `\n\nDiff:\n${changeset.diff}` : ''; return { id: `r${revision}`, title: `r${revision}: ${changeset.message}`, text: `Changeset r${revision}\nAuthor: ${changeset.author}\nDate: ${changeset.date}\n\nMessage:\n${changeset.message}${diffText}`, url: changesetUrl, metadata: { changeset }, }; } catch (error) { return { id: `r${revision}`, title: `Error loading changeset ${revision}`, text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`, url: `https://core.trac.wordpress.org/changeset/${revision}`, metadata: { error: true }, }; } }