mcp-pr-description 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +101 -0
  2. package/dist/adapters/github.d.ts +12 -0
  3. package/dist/adapters/github.d.ts.map +1 -0
  4. package/dist/adapters/github.js +73 -0
  5. package/dist/adapters/github.js.map +1 -0
  6. package/dist/index.d.ts +3 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +151 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/tools/generate-pr.d.ts +18 -0
  11. package/dist/tools/generate-pr.d.ts.map +1 -0
  12. package/dist/tools/generate-pr.js +114 -0
  13. package/dist/tools/generate-pr.js.map +1 -0
  14. package/dist/tools/learn-style.d.ts +7 -0
  15. package/dist/tools/learn-style.d.ts.map +1 -0
  16. package/dist/tools/learn-style.js +65 -0
  17. package/dist/tools/learn-style.js.map +1 -0
  18. package/dist/types.d.ts +45 -0
  19. package/dist/types.d.ts.map +1 -0
  20. package/dist/types.js +3 -0
  21. package/dist/types.js.map +1 -0
  22. package/dist/utils/file-writer.d.ts +2 -0
  23. package/dist/utils/file-writer.d.ts.map +1 -0
  24. package/dist/utils/file-writer.js +13 -0
  25. package/dist/utils/file-writer.js.map +1 -0
  26. package/dist/utils/git.d.ts +9 -0
  27. package/dist/utils/git.d.ts.map +1 -0
  28. package/dist/utils/git.js +83 -0
  29. package/dist/utils/git.js.map +1 -0
  30. package/dist/utils/style-cache.d.ts +5 -0
  31. package/dist/utils/style-cache.d.ts.map +1 -0
  32. package/dist/utils/style-cache.js +46 -0
  33. package/dist/utils/style-cache.js.map +1 -0
  34. package/dist/utils/style-extractor.d.ts +3 -0
  35. package/dist/utils/style-extractor.d.ts.map +1 -0
  36. package/dist/utils/style-extractor.js +87 -0
  37. package/dist/utils/style-extractor.js.map +1 -0
  38. package/package.json +40 -0
package/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # mcp-pr-description
2
+
3
+ An MCP (Model Context Protocol) server that generates PR descriptions by learning from your team's merged PRs.
4
+
5
+ ## Features
6
+
7
+ - **Learns your team's style** — Analyzes merged PRs to understand structure, tone, and patterns
8
+ - **Generates PRs in that style** — Uses git diff, branch name, and commits to create matching PRs
9
+ - **Saves to file** — Outputs `PR_DESCRIPTION.md` ready to copy-paste
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ # Clone and build
15
+ git clone <repo-url>
16
+ cd mcp-pr-description
17
+ npm install
18
+ npm run build
19
+
20
+ # Or install globally (after publishing)
21
+ npm install -g mcp-pr-description
22
+ ```
23
+
24
+ ## Setup
25
+
26
+ ### 1. Get a GitHub Token
27
+
28
+ Create a [GitHub Personal Access Token](https://github.com/settings/tokens) with `repo` scope.
29
+
30
+ ### 2. Configure MCP
31
+
32
+ Add to your MCP config file:
33
+
34
+ **VS Code (Augment):** Settings → search "augment mcp" → Edit in settings.json
35
+ **Cursor:** `~/.cursor/mcp.json`
36
+ **Claude Desktop:** `~/Library/Application Support/Claude/claude_desktop_config.json`
37
+
38
+ ```json
39
+ {
40
+ "mcpServers": {
41
+ "pr-description": {
42
+ "command": "npx",
43
+ "args": ["mcp-pr-description"],
44
+ "env": {
45
+ "GITHUB_TOKEN": "ghp_your_token_here"
46
+ }
47
+ }
48
+ }
49
+ }
50
+ ```
51
+
52
+ > **Note:** Using `npx` automatically resolves the package location. No need to specify a file path.
53
+
54
+ ## Usage
55
+
56
+ In your AI assistant, use natural language:
57
+
58
+ ```
59
+ "Learn our team's PR style"
60
+ → Analyzes last 20 merged PRs, saves patterns to .pr-style.json
61
+
62
+ "Generate a PR for my changes"
63
+ → Creates PR title + description based on your git changes
64
+
65
+ "Save the PR description"
66
+ → Writes PR_DESCRIPTION.md to your repo root
67
+ ```
68
+
69
+ ## Tools
70
+
71
+ | Tool | Description |
72
+ |------|-------------|
73
+ | `learn_pr_style` | Analyze merged PRs and learn team patterns |
74
+ | `generate_pr` | Generate PR from current git diff |
75
+ | `save_pr_description` | Save PR to `PR_DESCRIPTION.md` |
76
+ | `get_pr_style` | Display learned style patterns |
77
+
78
+ ## How It Works
79
+
80
+ 1. **Learn** — Fetches your last N merged PRs via GitHub API
81
+ 2. **Extract** — Identifies patterns: sections, tone, title format, ticket references
82
+ 3. **Cache** — Saves style to `.pr-style.json` (commit this for team sharing)
83
+ 4. **Generate** — Uses cached style + current git info to build PR prompt
84
+ 5. **Save** — Writes final PR to `PR_DESCRIPTION.md`
85
+
86
+ ## Output Files
87
+
88
+ - `.pr-style.json` — Cached team style (add to repo for team sharing)
89
+ - `PR_DESCRIPTION.md` — Generated PR description (copy to GitHub)
90
+
91
+ ## Development
92
+
93
+ ```bash
94
+ npm run dev # Watch mode
95
+ npm run build # Build for production
96
+ npm start # Run server
97
+ ```
98
+
99
+ ## License
100
+
101
+ MIT
@@ -0,0 +1,12 @@
1
+ import type { PRData } from '../types.js';
2
+ export declare class GitHubAdapter {
3
+ private octokit;
4
+ constructor(token?: string);
5
+ static parseRemoteUrl(remoteUrl: string): {
6
+ owner: string;
7
+ repo: string;
8
+ } | null;
9
+ fetchMergedPRs(owner: string, repo: string, count?: number): Promise<PRData[]>;
10
+ verifyAccess(owner: string, repo: string): Promise<boolean>;
11
+ }
12
+ //# sourceMappingURL=github.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/adapters/github.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAU;gBAEb,KAAK,CAAC,EAAE,MAAM;IAM1B,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAU1E,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAkDlF,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAQlE"}
@@ -0,0 +1,73 @@
1
+ import { Octokit } from '@octokit/rest';
2
+ export class GitHubAdapter {
3
+ octokit;
4
+ constructor(token) {
5
+ this.octokit = new Octokit({
6
+ auth: token || process.env.GITHUB_TOKEN,
7
+ });
8
+ }
9
+ static parseRemoteUrl(remoteUrl) {
10
+ const sshMatch = remoteUrl.match(/git@github\.com:([^/]+)\/(.+?)(\.git)?$/);
11
+ if (sshMatch)
12
+ return { owner: sshMatch[1], repo: sshMatch[2] };
13
+ const httpsMatch = remoteUrl.match(/github\.com\/([^/]+)\/(.+?)(\.git)?$/);
14
+ if (httpsMatch)
15
+ return { owner: httpsMatch[1], repo: httpsMatch[2] };
16
+ return null;
17
+ }
18
+ async fetchMergedPRs(owner, repo, count = 20) {
19
+ const { data: pullRequests } = await this.octokit.pulls.list({
20
+ owner,
21
+ repo,
22
+ state: 'closed',
23
+ sort: 'updated',
24
+ direction: 'desc',
25
+ per_page: count * 2,
26
+ });
27
+ const mergedPRs = pullRequests.filter(pr => pr.merged_at !== null).slice(0, count);
28
+ const detailedPRs = await Promise.all(mergedPRs.map(async (pr) => {
29
+ try {
30
+ const { data: details } = await this.octokit.pulls.get({
31
+ owner,
32
+ repo,
33
+ pull_number: pr.number,
34
+ });
35
+ return {
36
+ number: pr.number,
37
+ title: pr.title,
38
+ body: pr.body || '',
39
+ mergedAt: pr.merged_at || '',
40
+ author: pr.user?.login || 'unknown',
41
+ labels: pr.labels.map((l) => typeof l === 'string' ? l : l.name),
42
+ additions: details.additions,
43
+ deletions: details.deletions,
44
+ changedFiles: details.changed_files,
45
+ };
46
+ }
47
+ catch {
48
+ return {
49
+ number: pr.number,
50
+ title: pr.title,
51
+ body: pr.body || '',
52
+ mergedAt: pr.merged_at || '',
53
+ author: pr.user?.login || 'unknown',
54
+ labels: pr.labels.map((l) => typeof l === 'string' ? l : l.name),
55
+ additions: 0,
56
+ deletions: 0,
57
+ changedFiles: 0,
58
+ };
59
+ }
60
+ }));
61
+ return detailedPRs;
62
+ }
63
+ async verifyAccess(owner, repo) {
64
+ try {
65
+ await this.octokit.repos.get({ owner, repo });
66
+ return true;
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ }
72
+ }
73
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/adapters/github.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
+ import { learnPRStyle } from './tools/learn-style.js';
6
+ import { generatePR, savePRDescription, getLearnedStyle } from './tools/generate-pr.js';
7
+ const TOOLS = [
8
+ {
9
+ name: 'learn_pr_style',
10
+ description: 'Learn PR writing style from merged pull requests. ' +
11
+ 'Analyzes structure, tone, formatting, and common patterns. ' +
12
+ 'Run once per repo. Saves to .pr-style.json',
13
+ inputSchema: {
14
+ type: 'object',
15
+ properties: {
16
+ count: {
17
+ type: 'number',
18
+ description: 'Number of PRs to analyze (default: 20)',
19
+ default: 20,
20
+ },
21
+ },
22
+ },
23
+ },
24
+ {
25
+ name: 'generate_pr',
26
+ description: 'Generate PR title and description from current git changes. ' +
27
+ 'Uses learned team style if available. ' +
28
+ 'Analyzes branch name, commits, and file changes.',
29
+ inputSchema: {
30
+ type: 'object',
31
+ properties: {
32
+ baseBranch: {
33
+ type: 'string',
34
+ description: 'Base branch to compare (default: main)',
35
+ default: 'main',
36
+ },
37
+ includeDiff: {
38
+ type: 'boolean',
39
+ description: 'Include code diff in context (default: false)',
40
+ default: false,
41
+ },
42
+ },
43
+ },
44
+ },
45
+ {
46
+ name: 'save_pr_description',
47
+ description: 'Save generated PR title and description to PR_DESCRIPTION.md file. ' +
48
+ 'Call this after generate_pr to save the output.',
49
+ inputSchema: {
50
+ type: 'object',
51
+ properties: {
52
+ title: {
53
+ type: 'string',
54
+ description: 'PR title',
55
+ },
56
+ body: {
57
+ type: 'string',
58
+ description: 'PR description body (markdown)',
59
+ },
60
+ },
61
+ required: ['title', 'body'],
62
+ },
63
+ },
64
+ {
65
+ name: 'get_pr_style',
66
+ description: 'Show the learned PR style for this repository.',
67
+ inputSchema: {
68
+ type: 'object',
69
+ properties: {},
70
+ },
71
+ },
72
+ ];
73
+ const server = new Server({ name: 'mcp-pr-description', version: '1.0.0' }, { capabilities: { tools: {} } });
74
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
75
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
76
+ const { name, arguments: args = {} } = request.params;
77
+ try {
78
+ switch (name) {
79
+ case 'learn_pr_style': {
80
+ const count = typeof args.count === 'number' ? args.count : 20;
81
+ const result = await learnPRStyle(count);
82
+ return {
83
+ content: [{ type: 'text', text: result.displayText }],
84
+ isError: !result.success,
85
+ };
86
+ }
87
+ case 'generate_pr': {
88
+ const baseBranch = typeof args.baseBranch === 'string' ? args.baseBranch : 'main';
89
+ const includeDiff = typeof args.includeDiff === 'boolean' ? args.includeDiff : false;
90
+ const result = await generatePR(baseBranch, includeDiff);
91
+ if (!result.success) {
92
+ return {
93
+ content: [{ type: 'text', text: `❌ ${result.message}` }],
94
+ isError: true,
95
+ };
96
+ }
97
+ const prefix = result.hasLearnedStyle
98
+ ? ''
99
+ : '⚠️ No learned style. Run learn_pr_style first.\n\n';
100
+ return {
101
+ content: [{ type: 'text', text: prefix + (result.prompt || '') }],
102
+ isError: false,
103
+ };
104
+ }
105
+ case 'save_pr_description': {
106
+ const title = typeof args.title === 'string' ? args.title : '';
107
+ const body = typeof args.body === 'string' ? args.body : '';
108
+ if (!title || !body) {
109
+ return {
110
+ content: [{ type: 'text', text: '❌ Title and body are required' }],
111
+ isError: true,
112
+ };
113
+ }
114
+ const result = await savePRDescription(title, body);
115
+ return {
116
+ content: [{ type: 'text', text: result.success ? `✅ ${result.message}` : `❌ ${result.message}` }],
117
+ isError: !result.success,
118
+ };
119
+ }
120
+ case 'get_pr_style': {
121
+ const result = await getLearnedStyle();
122
+ return {
123
+ content: [{ type: 'text', text: result.displayText }],
124
+ isError: !result.success,
125
+ };
126
+ }
127
+ default:
128
+ return {
129
+ content: [{ type: 'text', text: `Unknown tool: ${name}` }],
130
+ isError: true,
131
+ };
132
+ }
133
+ }
134
+ catch (error) {
135
+ const msg = error instanceof Error ? error.message : 'Unknown error';
136
+ return {
137
+ content: [{ type: 'text', text: `Error: ${msg}` }],
138
+ isError: true,
139
+ };
140
+ }
141
+ });
142
+ async function main() {
143
+ const transport = new StdioServerTransport();
144
+ await server.connect(transport);
145
+ console.error('mcp-pr-description server started');
146
+ }
147
+ main().catch((error) => {
148
+ console.error('Fatal error:', error);
149
+ process.exit(1);
150
+ });
151
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface GeneratePRResult {
2
+ success: boolean;
3
+ prompt?: string;
4
+ filePath?: string;
5
+ message: string;
6
+ hasLearnedStyle: boolean;
7
+ }
8
+ export declare function generatePR(baseBranch?: string, includeDiff?: boolean, writeFile?: boolean): Promise<GeneratePRResult>;
9
+ export declare function savePRDescription(title: string, body: string): Promise<{
10
+ success: boolean;
11
+ filePath?: string;
12
+ message: string;
13
+ }>;
14
+ export declare function getLearnedStyle(): Promise<{
15
+ success: boolean;
16
+ displayText: string;
17
+ }>;
18
+ //# sourceMappingURL=generate-pr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-pr.d.ts","sourceRoot":"","sources":["../../src/tools/generate-pr.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAsB,UAAU,CAC9B,UAAU,GAAE,MAAe,EAC3B,WAAW,GAAE,OAAe,EAC5B,SAAS,GAAE,OAAc,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAuB3B;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5E,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAgBD;AA4DD,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAC/C,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAuBD"}
@@ -0,0 +1,114 @@
1
+ import { getGitInfo, getChangeSummary, getRepositoryRoot } from '../utils/git.js';
2
+ import { loadCachedStyle, formatStyleForDisplay } from '../utils/style-cache.js';
3
+ import { writePRDescriptionFile } from '../utils/file-writer.js';
4
+ export async function generatePR(baseBranch = 'main', includeDiff = false, writeFile = true) {
5
+ try {
6
+ const repoRoot = await getRepositoryRoot();
7
+ const gitInfo = await getGitInfo(undefined, baseBranch);
8
+ const changeSummary = await getChangeSummary(undefined, baseBranch);
9
+ const cachedStyle = await loadCachedStyle(repoRoot);
10
+ const prompt = buildPrompt(gitInfo, changeSummary, cachedStyle, includeDiff);
11
+ return {
12
+ success: true,
13
+ prompt,
14
+ message: 'PR context ready',
15
+ hasLearnedStyle: cachedStyle !== null,
16
+ };
17
+ }
18
+ catch (error) {
19
+ const msg = error instanceof Error ? error.message : 'Unknown error';
20
+ return {
21
+ success: false,
22
+ message: msg,
23
+ hasLearnedStyle: false,
24
+ };
25
+ }
26
+ }
27
+ export async function savePRDescription(title, body) {
28
+ try {
29
+ const repoRoot = await getRepositoryRoot();
30
+ const filePath = await writePRDescriptionFile(repoRoot, title, body);
31
+ return {
32
+ success: true,
33
+ filePath,
34
+ message: `PR description saved to ${filePath}`,
35
+ };
36
+ }
37
+ catch (error) {
38
+ const msg = error instanceof Error ? error.message : 'Unknown error';
39
+ return {
40
+ success: false,
41
+ message: `Failed to save: ${msg}`,
42
+ };
43
+ }
44
+ }
45
+ function buildPrompt(gitInfo, changeSummary, style, includeDiff) {
46
+ const sections = [
47
+ 'Generate a pull request title and description based on the following.',
48
+ '',
49
+ ];
50
+ if (style) {
51
+ sections.push('## Team PR Style (FOLLOW THIS EXACTLY)');
52
+ sections.push('');
53
+ sections.push(formatStyleForDisplay(style));
54
+ sections.push('');
55
+ }
56
+ else {
57
+ sections.push('## Note: No learned style found. Run `learn_pr_style` first for better results.');
58
+ sections.push('');
59
+ }
60
+ sections.push(`## Branch: \`${gitInfo.branchName}\``);
61
+ sections.push('');
62
+ if (gitInfo.commitMessages.length > 0) {
63
+ sections.push('## Commits');
64
+ gitInfo.commitMessages.forEach(m => sections.push(`- ${m}`));
65
+ sections.push('');
66
+ }
67
+ sections.push('## Files Changed');
68
+ sections.push('```');
69
+ sections.push(changeSummary);
70
+ sections.push('```');
71
+ sections.push('');
72
+ if (includeDiff && gitInfo.diff) {
73
+ const maxLen = 6000;
74
+ const diff = gitInfo.diff.length > maxLen
75
+ ? gitInfo.diff.slice(0, maxLen) + '\n... (truncated)'
76
+ : gitInfo.diff;
77
+ sections.push('## Diff');
78
+ sections.push('```diff');
79
+ sections.push(diff);
80
+ sections.push('```');
81
+ sections.push('');
82
+ }
83
+ sections.push('## Instructions');
84
+ sections.push('Generate:');
85
+ sections.push('1. **Title** - concise, following team style if available');
86
+ sections.push('2. **Description** - full PR body with appropriate sections');
87
+ sections.push('');
88
+ sections.push('After generating, call `save_pr_description` to save as PR_DESCRIPTION.md');
89
+ return sections.join('\n');
90
+ }
91
+ export async function getLearnedStyle() {
92
+ try {
93
+ const repoRoot = await getRepositoryRoot();
94
+ const style = await loadCachedStyle(repoRoot);
95
+ if (!style) {
96
+ return {
97
+ success: false,
98
+ displayText: '❌ No learned style. Run `learn_pr_style` first.',
99
+ };
100
+ }
101
+ return {
102
+ success: true,
103
+ displayText: formatStyleForDisplay(style),
104
+ };
105
+ }
106
+ catch (error) {
107
+ const msg = error instanceof Error ? error.message : 'Unknown error';
108
+ return {
109
+ success: false,
110
+ displayText: `❌ Error: ${msg}`,
111
+ };
112
+ }
113
+ }
114
+ //# sourceMappingURL=generate-pr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-pr.js","sourceRoot":"","sources":["../../src/tools/generate-pr.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface LearnStyleResult {
2
+ success: boolean;
3
+ message: string;
4
+ displayText: string;
5
+ }
6
+ export declare function learnPRStyle(count?: number): Promise<LearnStyleResult>;
7
+ //# sourceMappingURL=learn-style.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learn-style.d.ts","sourceRoot":"","sources":["../../src/tools/learn-style.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,YAAY,CAAC,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAkEhF"}
@@ -0,0 +1,65 @@
1
+ import { GitHubAdapter } from '../adapters/github.js';
2
+ import { extractStyleFromPRs } from '../utils/style-extractor.js';
3
+ import { saveCachedStyle, formatStyleForDisplay } from '../utils/style-cache.js';
4
+ import { getRepositoryRoot, getRemoteUrl } from '../utils/git.js';
5
+ export async function learnPRStyle(count = 20) {
6
+ try {
7
+ const repoRoot = await getRepositoryRoot();
8
+ const remoteUrl = await getRemoteUrl();
9
+ const repoInfo = GitHubAdapter.parseRemoteUrl(remoteUrl);
10
+ if (!repoInfo) {
11
+ return {
12
+ success: false,
13
+ message: `Could not parse GitHub repository from: ${remoteUrl}`,
14
+ displayText: '❌ Not a GitHub repository or invalid remote URL',
15
+ };
16
+ }
17
+ if (!process.env.GITHUB_TOKEN) {
18
+ return {
19
+ success: false,
20
+ message: 'GITHUB_TOKEN not set',
21
+ displayText: '❌ GITHUB_TOKEN environment variable is required',
22
+ };
23
+ }
24
+ const github = new GitHubAdapter();
25
+ const { owner, repo } = repoInfo;
26
+ const hasAccess = await github.verifyAccess(owner, repo);
27
+ if (!hasAccess) {
28
+ return {
29
+ success: false,
30
+ message: `No access to ${owner}/${repo}`,
31
+ displayText: `❌ Cannot access ${owner}/${repo}. Check your GITHUB_TOKEN.`,
32
+ };
33
+ }
34
+ const prs = await github.fetchMergedPRs(owner, repo, count);
35
+ if (prs.length === 0) {
36
+ return {
37
+ success: false,
38
+ message: 'No merged PRs found',
39
+ displayText: '⚠️ No merged PRs found in repository',
40
+ };
41
+ }
42
+ const style = extractStyleFromPRs(prs, owner, repo);
43
+ await saveCachedStyle(repoRoot, style);
44
+ return {
45
+ success: true,
46
+ message: `Learned from ${prs.length} PRs`,
47
+ displayText: [
48
+ `✅ Learned PR style from ${prs.length} merged PRs!`,
49
+ '',
50
+ formatStyleForDisplay(style),
51
+ '',
52
+ `📁 Saved to: ${repoRoot}/.pr-style.json`,
53
+ ].join('\n'),
54
+ };
55
+ }
56
+ catch (error) {
57
+ const msg = error instanceof Error ? error.message : 'Unknown error';
58
+ return {
59
+ success: false,
60
+ message: msg,
61
+ displayText: `❌ Error: ${msg}`,
62
+ };
63
+ }
64
+ }
65
+ //# sourceMappingURL=learn-style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learn-style.js","sourceRoot":"","sources":["../../src/tools/learn-style.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAQlE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB,EAAE;IACnD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,iBAAiB,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;QAEvC,MAAM,QAAQ,GAAG,aAAa,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACzD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,2CAA2C,SAAS,EAAE;gBAC/D,WAAW,EAAE,iDAAiD;aAC/D,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC9B,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,sBAAsB;gBAC/B,WAAW,EAAE,iDAAiD;aAC/D,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QACnC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;QAEjC,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,gBAAgB,KAAK,IAAI,IAAI,EAAE;gBACxC,WAAW,EAAE,mBAAmB,KAAK,IAAI,IAAI,4BAA4B;aAC1E,CAAC;QACJ,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAE5D,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,qBAAqB;gBAC9B,WAAW,EAAE,sCAAsC;aACpD,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,mBAAmB,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QACpD,MAAM,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAEvC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,gBAAgB,GAAG,CAAC,MAAM,MAAM;YACzC,WAAW,EAAE;gBACX,2BAA2B,GAAG,CAAC,MAAM,cAAc;gBACnD,EAAE;gBACF,qBAAqB,CAAC,KAAK,CAAC;gBAC5B,EAAE;gBACF,gBAAgB,QAAQ,iBAAiB;aAC1C,CAAC,IAAI,CAAC,IAAI,CAAC;SACb,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACrE,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,GAAG;YACZ,WAAW,EAAE,YAAY,GAAG,EAAE;SAC/B,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,45 @@
1
+ export interface PRData {
2
+ number: number;
3
+ title: string;
4
+ body: string;
5
+ mergedAt: string;
6
+ author: string;
7
+ labels: string[];
8
+ additions: number;
9
+ deletions: number;
10
+ changedFiles: number;
11
+ }
12
+ export interface LearnedStyle {
13
+ sections: string[];
14
+ usesCheckboxes: boolean;
15
+ usesBulletPoints: boolean;
16
+ usesNumberedLists: boolean;
17
+ titlePattern: string | null;
18
+ titlePrefixExamples: string[];
19
+ averageBodyLength: number;
20
+ averageLineCount: number;
21
+ mentionsTickets: boolean;
22
+ ticketPattern: string | null;
23
+ tone: 'formal' | 'casual' | 'mixed';
24
+ usesFirstPerson: boolean;
25
+ usesEmojis: boolean;
26
+ alwaysIncludes: string[];
27
+ sampleCount: number;
28
+ lastUpdated: string;
29
+ repositoryInfo: {
30
+ owner: string;
31
+ repo: string;
32
+ };
33
+ }
34
+ export interface GitInfo {
35
+ diff: string;
36
+ branchName: string;
37
+ commitMessages: string[];
38
+ stagedFiles: string[];
39
+ repositoryRoot: string;
40
+ }
41
+ export interface GeneratedPR {
42
+ title: string;
43
+ body: string;
44
+ }
45
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE;QACd,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ // Types for PR style learning and generation
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,6CAA6C"}
@@ -0,0 +1,2 @@
1
+ export declare function writePRDescriptionFile(repoRoot: string, title: string, body: string): Promise<string>;
2
+ //# sourceMappingURL=file-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-writer.d.ts","sourceRoot":"","sources":["../../src/utils/file-writer.ts"],"names":[],"mappings":"AAGA,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAWjB"}
@@ -0,0 +1,13 @@
1
+ import { writeFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ export async function writePRDescriptionFile(repoRoot, title, body) {
4
+ const filename = 'PR_DESCRIPTION.md';
5
+ const filepath = join(repoRoot, filename);
6
+ const content = `# ${title}
7
+
8
+ ${body}
9
+ `;
10
+ await writeFile(filepath, content, 'utf-8');
11
+ return filepath;
12
+ }
13
+ //# sourceMappingURL=file-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-writer.js","sourceRoot":"","sources":["../../src/utils/file-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,QAAgB,EAChB,KAAa,EACb,IAAY;IAEZ,MAAM,QAAQ,GAAG,mBAAmB,CAAC;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAE1C,MAAM,OAAO,GAAG,KAAK,KAAK;;EAE1B,IAAI;CACL,CAAC;IAEA,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { GitInfo } from '../types.js';
2
+ export declare function getRepositoryRoot(cwd?: string): Promise<string>;
3
+ export declare function getBranchName(cwd?: string): Promise<string>;
4
+ export declare function getRemoteUrl(cwd?: string): Promise<string>;
5
+ export declare function getDiff(cwd?: string, baseBranch?: string): Promise<string>;
6
+ export declare function getCommitMessages(cwd?: string, baseBranch?: string): Promise<string[]>;
7
+ export declare function getChangeSummary(cwd?: string, baseBranch?: string): Promise<string>;
8
+ export declare function getGitInfo(cwd?: string, baseBranch?: string): Promise<GitInfo>;
9
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAY3C,wBAAsB,iBAAiB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAErE;AAED,wBAAsB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEjE;AAED,wBAAsB,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMhE;AAED,wBAAsB,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBhF;AAED,wBAAsB,iBAAiB,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAc5F;AAED,wBAAsB,gBAAgB,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAYzF;AAED,wBAAsB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASpF"}
@@ -0,0 +1,83 @@
1
+ import { exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+ const execAsync = promisify(exec);
4
+ async function gitCommand(command, cwd) {
5
+ const { stdout } = await execAsync(command, {
6
+ cwd: cwd || process.cwd(),
7
+ maxBuffer: 10 * 1024 * 1024
8
+ });
9
+ return stdout.trim();
10
+ }
11
+ export async function getRepositoryRoot(cwd) {
12
+ return gitCommand('git rev-parse --show-toplevel', cwd);
13
+ }
14
+ export async function getBranchName(cwd) {
15
+ return gitCommand('git branch --show-current', cwd);
16
+ }
17
+ export async function getRemoteUrl(cwd) {
18
+ try {
19
+ return await gitCommand('git remote get-url origin', cwd);
20
+ }
21
+ catch {
22
+ return gitCommand('git remote get-url upstream', cwd);
23
+ }
24
+ }
25
+ export async function getDiff(cwd, baseBranch) {
26
+ const base = baseBranch || 'main';
27
+ try {
28
+ const diff = await gitCommand(`git diff ${base}...HEAD`, cwd);
29
+ if (diff)
30
+ return diff;
31
+ }
32
+ catch {
33
+ try {
34
+ const diff = await gitCommand(`git diff origin/${base}...HEAD`, cwd);
35
+ if (diff)
36
+ return diff;
37
+ }
38
+ catch { }
39
+ }
40
+ const staged = await gitCommand('git diff --cached', cwd);
41
+ const unstaged = await gitCommand('git diff', cwd);
42
+ return [staged, unstaged].filter(Boolean).join('\n');
43
+ }
44
+ export async function getCommitMessages(cwd, baseBranch) {
45
+ const base = baseBranch || 'main';
46
+ try {
47
+ const log = await gitCommand(`git log ${base}..HEAD --pretty=format:"%s"`, cwd);
48
+ return log.split('\n').filter(Boolean);
49
+ }
50
+ catch {
51
+ try {
52
+ const log = await gitCommand(`git log origin/${base}..HEAD --pretty=format:"%s"`, cwd);
53
+ return log.split('\n').filter(Boolean);
54
+ }
55
+ catch {
56
+ return [];
57
+ }
58
+ }
59
+ }
60
+ export async function getChangeSummary(cwd, baseBranch) {
61
+ const base = baseBranch || 'main';
62
+ try {
63
+ return await gitCommand(`git diff ${base}...HEAD --stat`, cwd);
64
+ }
65
+ catch {
66
+ try {
67
+ return await gitCommand(`git diff origin/${base}...HEAD --stat`, cwd);
68
+ }
69
+ catch {
70
+ return await gitCommand('git diff --stat', cwd);
71
+ }
72
+ }
73
+ }
74
+ export async function getGitInfo(cwd, baseBranch) {
75
+ const [repositoryRoot, branchName, diff, commitMessages] = await Promise.all([
76
+ getRepositoryRoot(cwd),
77
+ getBranchName(cwd),
78
+ getDiff(cwd, baseBranch),
79
+ getCommitMessages(cwd, baseBranch),
80
+ ]);
81
+ return { repositoryRoot, branchName, diff, commitMessages, stagedFiles: [] };
82
+ }
83
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { LearnedStyle } from '../types.js';
2
+ export declare function loadCachedStyle(repoRoot: string): Promise<LearnedStyle | null>;
3
+ export declare function saveCachedStyle(repoRoot: string, style: LearnedStyle): Promise<void>;
4
+ export declare function formatStyleForDisplay(style: LearnedStyle): string;
5
+ //# sourceMappingURL=style-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-cache.d.ts","sourceRoot":"","sources":["../../src/utils/style-cache.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAUpF;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1F;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CA0BjE"}
@@ -0,0 +1,46 @@
1
+ import { readFile, writeFile } from 'fs/promises';
2
+ import { existsSync } from 'fs';
3
+ import { join } from 'path';
4
+ const CACHE_FILENAME = '.pr-style.json';
5
+ export async function loadCachedStyle(repoRoot) {
6
+ const cachePath = join(repoRoot, CACHE_FILENAME);
7
+ if (!existsSync(cachePath))
8
+ return null;
9
+ try {
10
+ const content = await readFile(cachePath, 'utf-8');
11
+ return JSON.parse(content);
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ }
17
+ export async function saveCachedStyle(repoRoot, style) {
18
+ const cachePath = join(repoRoot, CACHE_FILENAME);
19
+ await writeFile(cachePath, JSON.stringify(style, null, 2), 'utf-8');
20
+ }
21
+ export function formatStyleForDisplay(style) {
22
+ const lines = [
23
+ `## Learned PR Style for ${style.repositoryInfo.owner}/${style.repositoryInfo.repo}`,
24
+ `Based on ${style.sampleCount} merged PRs (updated: ${new Date(style.lastUpdated).toLocaleDateString()})`,
25
+ '',
26
+ '### Structure',
27
+ `- Sections: ${style.sections.length > 0 ? style.sections.join(', ') : 'None detected'}`,
28
+ `- Checkboxes: ${style.usesCheckboxes ? 'Yes' : 'No'}`,
29
+ `- Bullet points: ${style.usesBulletPoints ? 'Yes' : 'No'}`,
30
+ `- Average length: ~${style.averageLineCount} lines`,
31
+ '',
32
+ '### Title Style',
33
+ `- Pattern: ${style.titlePattern || 'No consistent pattern'}`,
34
+ `- Prefixes: ${style.titlePrefixExamples.length > 0 ? style.titlePrefixExamples.join(', ') : 'None'}`,
35
+ '',
36
+ '### Tone',
37
+ `- Style: ${style.tone}`,
38
+ `- First person: ${style.usesFirstPerson ? 'Yes' : 'No'}`,
39
+ `- Emojis: ${style.usesEmojis ? 'Yes' : 'No'}`,
40
+ ];
41
+ if (style.mentionsTickets) {
42
+ lines.push('', '### Tickets', `- Pattern: ${style.ticketPattern}`);
43
+ }
44
+ return lines.join('\n');
45
+ }
46
+ //# sourceMappingURL=style-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-cache.js","sourceRoot":"","sources":["../../src/utils/style-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB;IACpD,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAExC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAiB,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB,EAAE,KAAmB;IACzE,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IACjD,MAAM,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAmB;IACvD,MAAM,KAAK,GAAa;QACtB,2BAA2B,KAAK,CAAC,cAAc,CAAC,KAAK,IAAI,KAAK,CAAC,cAAc,CAAC,IAAI,EAAE;QACpF,YAAY,KAAK,CAAC,WAAW,yBAAyB,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,kBAAkB,EAAE,GAAG;QACzG,EAAE;QACF,eAAe;QACf,eAAe,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,eAAe,EAAE;QACxF,iBAAiB,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;QACtD,oBAAoB,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;QAC3D,sBAAsB,KAAK,CAAC,gBAAgB,QAAQ;QACpD,EAAE;QACF,iBAAiB;QACjB,cAAc,KAAK,CAAC,YAAY,IAAI,uBAAuB,EAAE;QAC7D,eAAe,KAAK,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE;QACrG,EAAE;QACF,UAAU;QACV,YAAY,KAAK,CAAC,IAAI,EAAE;QACxB,mBAAmB,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;QACzD,aAAa,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;KAC/C,CAAC;IAEF,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,EAAE,cAAc,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { PRData, LearnedStyle } from '../types.js';
2
+ export declare function extractStyleFromPRs(prs: PRData[], owner: string, repo: string): LearnedStyle;
3
+ //# sourceMappingURL=style-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-extractor.d.ts","sourceRoot":"","sources":["../../src/utils/style-extractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAExD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAuB5F"}
@@ -0,0 +1,87 @@
1
+ export function extractStyleFromPRs(prs, owner, repo) {
2
+ const bodies = prs.map(pr => pr.body).filter(Boolean);
3
+ const titles = prs.map(pr => pr.title);
4
+ return {
5
+ sections: extractCommonSections(bodies),
6
+ usesCheckboxes: bodies.some(b => /\[[ x]\]/.test(b)),
7
+ usesBulletPoints: bodies.some(b => /^[\s]*[-*]\s/m.test(b)),
8
+ usesNumberedLists: bodies.some(b => /^\s*\d+\.\s/m.test(b)),
9
+ titlePattern: detectTitlePattern(titles),
10
+ titlePrefixExamples: extractTitlePrefixes(titles),
11
+ averageBodyLength: avg(bodies.map(b => b.length)),
12
+ averageLineCount: avg(bodies.map(b => b.split('\n').length)),
13
+ mentionsTickets: bodies.some(b => /[A-Z]+-\d+/.test(b)),
14
+ ticketPattern: detectTicketPattern([...bodies, ...titles]),
15
+ tone: analyzeTone(bodies),
16
+ usesFirstPerson: bodies.some(b => /\b(I |I'|my |we |we'|our )/i.test(b)),
17
+ usesEmojis: bodies.some(b => hasEmoji(b)) || titles.some(t => hasEmoji(t)),
18
+ alwaysIncludes: extractCommonPhrases(bodies),
19
+ sampleCount: prs.length,
20
+ lastUpdated: new Date().toISOString(),
21
+ repositoryInfo: { owner, repo },
22
+ };
23
+ }
24
+ function extractCommonSections(bodies) {
25
+ const counts = new Map();
26
+ for (const body of bodies) {
27
+ const headers = body.match(/^#{1,3}\s+.+$/gm) || [];
28
+ for (const h of headers)
29
+ counts.set(h.trim(), (counts.get(h.trim()) || 0) + 1);
30
+ }
31
+ const threshold = bodies.length * 0.3;
32
+ return Array.from(counts.entries())
33
+ .filter(([, c]) => c >= threshold)
34
+ .sort((a, b) => b[1] - a[1])
35
+ .map(([s]) => s);
36
+ }
37
+ function detectTitlePattern(titles) {
38
+ const conventional = titles.filter(t => /^(feat|fix|docs|style|refactor|test|chore|build|ci|perf|revert)(\(.+\))?:\s/.test(t)).length;
39
+ if (conventional > titles.length * 0.5)
40
+ return 'conventional';
41
+ const ticketPrefix = titles.filter(t => /^\[?[A-Z]+-\d+\]?\s/.test(t)).length;
42
+ if (ticketPrefix > titles.length * 0.5)
43
+ return 'ticket-prefix';
44
+ return null;
45
+ }
46
+ function extractTitlePrefixes(titles) {
47
+ const prefixes = new Set();
48
+ for (const title of titles) {
49
+ const conv = title.match(/^(feat|fix|docs|style|refactor|test|chore|build|ci|perf|revert):/);
50
+ if (conv)
51
+ prefixes.add(conv[1] + ':');
52
+ }
53
+ return Array.from(prefixes);
54
+ }
55
+ function avg(nums) {
56
+ return nums.length ? Math.round(nums.reduce((a, b) => a + b, 0) / nums.length) : 0;
57
+ }
58
+ function detectTicketPattern(texts) {
59
+ const combined = texts.join(' ');
60
+ if (/JIRA-\d+/.test(combined))
61
+ return 'JIRA-\\d+';
62
+ if (/[A-Z]{2,}-\d+/.test(combined))
63
+ return '[A-Z]{2,}-\\d+';
64
+ return null;
65
+ }
66
+ function analyzeTone(bodies) {
67
+ let formal = 0, casual = 0;
68
+ for (const b of bodies) {
69
+ if (/\b(This PR|This commit|This change)\b/i.test(b))
70
+ formal++;
71
+ if (/\b(I |we |gonna|wanna|lol)\b/i.test(b))
72
+ casual++;
73
+ }
74
+ if (formal > bodies.length * 0.5)
75
+ return 'formal';
76
+ if (casual > bodies.length * 0.3)
77
+ return 'casual';
78
+ return 'mixed';
79
+ }
80
+ function hasEmoji(text) {
81
+ return /[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]/u.test(text);
82
+ }
83
+ function extractCommonPhrases(bodies) {
84
+ const phrases = ['## Description', '## Testing', '## Changes', 'Fixes #', 'Closes #'];
85
+ return phrases.filter(p => bodies.filter(b => b.includes(p)).length > bodies.length * 0.5);
86
+ }
87
+ //# sourceMappingURL=style-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-extractor.js","sourceRoot":"","sources":["../../src/utils/style-extractor.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "mcp-pr-description",
3
+ "version": "1.0.0",
4
+ "description": "MCP server that generates PR descriptions by learning from your team's merged PRs",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "mcp-pr-description": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "start": "node dist/index.js",
16
+ "dev": "tsc --watch",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "model-context-protocol",
22
+ "pull-request",
23
+ "github",
24
+ "ai",
25
+ "pr-description"
26
+ ],
27
+ "author": "",
28
+ "license": "MIT",
29
+ "dependencies": {
30
+ "@modelcontextprotocol/sdk": "^1.0.0",
31
+ "@octokit/rest": "^21.0.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^22.0.0",
35
+ "typescript": "^5.7.0"
36
+ },
37
+ "engines": {
38
+ "node": ">=18.0.0"
39
+ }
40
+ }