@andrebuzeli/git-mcp 5.5.0 → 5.5.2
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.
- package/README.md +25 -0
- package/dist/config.d.ts +5 -131
- package/dist/config.js +28 -430
- package/dist/index.d.ts +1 -21
- package/dist/index.js +66 -144
- package/dist/providers/giteaProvider.d.ts +3 -0
- package/dist/providers/giteaProvider.js +12 -0
- package/dist/providers/githubProvider.d.ts +2 -0
- package/dist/providers/githubProvider.js +7 -0
- package/dist/providers/providerManager.d.ts +11 -0
- package/dist/providers/providerManager.js +48 -0
- package/dist/server.d.ts +6 -40
- package/dist/server.js +30 -700
- package/dist/tools/gitAnalytics.d.ts +29 -0
- package/dist/tools/gitAnalytics.js +72 -0
- package/dist/tools/gitArchive.d.ts +6 -0
- package/dist/tools/gitArchive.js +27 -0
- package/dist/tools/gitBackup.d.ts +10 -0
- package/dist/tools/gitBackup.js +44 -0
- package/dist/tools/gitBranches.d.ts +72 -0
- package/dist/tools/gitBranches.js +97 -0
- package/dist/tools/gitConfig.d.ts +34 -0
- package/dist/tools/gitConfig.js +73 -0
- package/dist/tools/gitFiles.d.ts +24 -0
- package/dist/tools/gitFiles.js +53 -0
- package/dist/tools/gitIssues.d.ts +21 -0
- package/dist/tools/gitIssues.js +193 -0
- package/dist/tools/gitMonitor.d.ts +51 -0
- package/dist/tools/gitMonitor.js +102 -0
- package/dist/tools/gitPackages.d.ts +6 -0
- package/dist/tools/gitPackages.js +28 -0
- package/dist/tools/gitPulls.d.ts +74 -0
- package/dist/tools/gitPulls.js +190 -0
- package/dist/tools/gitRelease.d.ts +34 -0
- package/dist/tools/gitRelease.js +99 -0
- package/dist/tools/gitRemote.d.ts +51 -0
- package/dist/tools/gitRemote.js +68 -0
- package/dist/tools/gitReset.d.ts +34 -0
- package/dist/tools/gitReset.js +64 -0
- package/dist/tools/gitStash.d.ts +41 -0
- package/dist/tools/gitStash.js +67 -0
- package/dist/tools/gitSync.d.ts +25 -0
- package/dist/tools/gitSync.js +51 -0
- package/dist/tools/gitTags.d.ts +30 -0
- package/dist/tools/gitTags.js +69 -0
- package/dist/tools/gitWorkflow.d.ts +69 -0
- package/dist/tools/gitWorkflow.js +129 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.js +2 -0
- package/dist/utils/errors.d.ts +13 -0
- package/dist/utils/errors.js +22 -0
- package/dist/utils/safetyController.d.ts +1 -0
- package/dist/utils/safetyController.js +15 -0
- package/package.json +7 -2
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/providers/base-provider.d.ts +0 -66
- package/dist/providers/base-provider.d.ts.map +0 -1
- package/dist/providers/base-provider.js +0 -65
- package/dist/providers/base-provider.js.map +0 -1
- package/dist/providers/gitea-provider.d.ts +0 -79
- package/dist/providers/gitea-provider.d.ts.map +0 -1
- package/dist/providers/gitea-provider.js +0 -576
- package/dist/providers/gitea-provider.js.map +0 -1
- package/dist/providers/github-provider.d.ts +0 -74
- package/dist/providers/github-provider.d.ts.map +0 -1
- package/dist/providers/github-provider.js +0 -683
- package/dist/providers/github-provider.js.map +0 -1
- package/dist/providers/index.d.ts +0 -13
- package/dist/providers/index.d.ts.map +0 -1
- package/dist/providers/index.js +0 -35
- package/dist/providers/index.js.map +0 -1
- package/dist/providers/provider-factory.d.ts +0 -49
- package/dist/providers/provider-factory.d.ts.map +0 -1
- package/dist/providers/provider-factory.js +0 -193
- package/dist/providers/provider-factory.js.map +0 -1
- package/dist/providers/provider-operation-handler.d.ts +0 -115
- package/dist/providers/provider-operation-handler.d.ts.map +0 -1
- package/dist/providers/provider-operation-handler.js +0 -449
- package/dist/providers/provider-operation-handler.js.map +0 -1
- package/dist/providers/types.d.ts +0 -200
- package/dist/providers/types.d.ts.map +0 -1
- package/dist/providers/types.js +0 -8
- package/dist/providers/types.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/tools/git-analytics.d.ts +0 -237
- package/dist/tools/git-analytics.d.ts.map +0 -1
- package/dist/tools/git-analytics.js +0 -828
- package/dist/tools/git-analytics.js.map +0 -1
- package/dist/tools/git-archive.d.ts +0 -113
- package/dist/tools/git-archive.d.ts.map +0 -1
- package/dist/tools/git-archive.js +0 -466
- package/dist/tools/git-archive.js.map +0 -1
- package/dist/tools/git-auto-monitor.d.ts +0 -180
- package/dist/tools/git-auto-monitor.d.ts.map +0 -1
- package/dist/tools/git-auto-monitor.js +0 -522
- package/dist/tools/git-auto-monitor.js.map +0 -1
- package/dist/tools/git-backup.d.ts +0 -105
- package/dist/tools/git-backup.d.ts.map +0 -1
- package/dist/tools/git-backup.js +0 -414
- package/dist/tools/git-backup.js.map +0 -1
- package/dist/tools/git-branches.d.ts +0 -183
- package/dist/tools/git-branches.d.ts.map +0 -1
- package/dist/tools/git-branches.js +0 -507
- package/dist/tools/git-branches.js.map +0 -1
- package/dist/tools/git-config.d.ts +0 -119
- package/dist/tools/git-config.d.ts.map +0 -1
- package/dist/tools/git-config.js +0 -449
- package/dist/tools/git-config.js.map +0 -1
- package/dist/tools/git-files.d.ts +0 -150
- package/dist/tools/git-files.d.ts.map +0 -1
- package/dist/tools/git-files.js +0 -536
- package/dist/tools/git-files.js.map +0 -1
- package/dist/tools/git-history.d.ts +0 -253
- package/dist/tools/git-history.d.ts.map +0 -1
- package/dist/tools/git-history.js +0 -824
- package/dist/tools/git-history.js.map +0 -1
- package/dist/tools/git-issues.d.ts +0 -164
- package/dist/tools/git-issues.d.ts.map +0 -1
- package/dist/tools/git-issues.js +0 -349
- package/dist/tools/git-issues.js.map +0 -1
- package/dist/tools/git-monitor.d.ts +0 -154
- package/dist/tools/git-monitor.d.ts.map +0 -1
- package/dist/tools/git-monitor.js +0 -531
- package/dist/tools/git-monitor.js.map +0 -1
- package/dist/tools/git-packages.d.ts +0 -157
- package/dist/tools/git-packages.d.ts.map +0 -1
- package/dist/tools/git-packages.js +0 -534
- package/dist/tools/git-packages.js.map +0 -1
- package/dist/tools/git-pulls.d.ts +0 -180
- package/dist/tools/git-pulls.d.ts.map +0 -1
- package/dist/tools/git-pulls.js +0 -378
- package/dist/tools/git-pulls.js.map +0 -1
- package/dist/tools/git-release.d.ts +0 -161
- package/dist/tools/git-release.d.ts.map +0 -1
- package/dist/tools/git-release.js +0 -466
- package/dist/tools/git-release.js.map +0 -1
- package/dist/tools/git-remote.d.ts +0 -128
- package/dist/tools/git-remote.d.ts.map +0 -1
- package/dist/tools/git-remote.js +0 -542
- package/dist/tools/git-remote.js.map +0 -1
- package/dist/tools/git-reset.d.ts +0 -120
- package/dist/tools/git-reset.d.ts.map +0 -1
- package/dist/tools/git-reset.js +0 -479
- package/dist/tools/git-reset.js.map +0 -1
- package/dist/tools/git-stash.d.ts +0 -124
- package/dist/tools/git-stash.d.ts.map +0 -1
- package/dist/tools/git-stash.js +0 -506
- package/dist/tools/git-stash.js.map +0 -1
- package/dist/tools/git-sync.d.ts +0 -154
- package/dist/tools/git-sync.d.ts.map +0 -1
- package/dist/tools/git-sync.js +0 -479
- package/dist/tools/git-sync.js.map +0 -1
- package/dist/tools/git-tags.d.ts +0 -136
- package/dist/tools/git-tags.d.ts.map +0 -1
- package/dist/tools/git-tags.js +0 -470
- package/dist/tools/git-tags.js.map +0 -1
- package/dist/tools/git-update.d.ts +0 -224
- package/dist/tools/git-update.d.ts.map +0 -1
- package/dist/tools/git-update.js +0 -948
- package/dist/tools/git-update.js.map +0 -1
- package/dist/tools/git-workflow.d.ts +0 -189
- package/dist/tools/git-workflow.d.ts.map +0 -1
- package/dist/tools/git-workflow.js +0 -551
- package/dist/tools/git-workflow.js.map +0 -1
- package/dist/utils/credential-manager.d.ts +0 -119
- package/dist/utils/credential-manager.d.ts.map +0 -1
- package/dist/utils/credential-manager.js +0 -450
- package/dist/utils/credential-manager.js.map +0 -1
- package/dist/utils/data-merger.d.ts +0 -49
- package/dist/utils/data-merger.d.ts.map +0 -1
- package/dist/utils/data-merger.js +0 -233
- package/dist/utils/data-merger.js.map +0 -1
- package/dist/utils/git-command-executor.d.ts +0 -330
- package/dist/utils/git-command-executor.d.ts.map +0 -1
- package/dist/utils/git-command-executor.js +0 -901
- package/dist/utils/git-command-executor.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -143
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -473
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/operation-error-handler.d.ts +0 -97
- package/dist/utils/operation-error-handler.d.ts.map +0 -1
- package/dist/utils/operation-error-handler.js +0 -367
- package/dist/utils/operation-error-handler.js.map +0 -1
- package/dist/utils/parameter-validator.d.ts +0 -49
- package/dist/utils/parameter-validator.d.ts.map +0 -1
- package/dist/utils/parameter-validator.js +0 -647
- package/dist/utils/parameter-validator.js.map +0 -1
- package/dist/utils/repository-checker.d.ts +0 -46
- package/dist/utils/repository-checker.d.ts.map +0 -1
- package/dist/utils/repository-checker.js +0 -151
- package/dist/utils/repository-checker.js.map +0 -1
- package/dist/utils/repository-detector.d.ts +0 -128
- package/dist/utils/repository-detector.d.ts.map +0 -1
- package/dist/utils/repository-detector.js +0 -422
- package/dist/utils/repository-detector.js.map +0 -1
- package/dist/utils/repository-sync.d.ts +0 -67
- package/dist/utils/repository-sync.d.ts.map +0 -1
- package/dist/utils/repository-sync.js +0 -344
- package/dist/utils/repository-sync.js.map +0 -1
- package/dist/utils/response-formatter.d.ts +0 -146
- package/dist/utils/response-formatter.d.ts.map +0 -1
- package/dist/utils/response-formatter.js +0 -378
- package/dist/utils/response-formatter.js.map +0 -1
- package/dist/utils/retry.d.ts +0 -12
- package/dist/utils/retry.d.ts.map +0 -1
- package/dist/utils/retry.js +0 -28
- package/dist/utils/retry.js.map +0 -1
- package/dist/utils/safety-warnings.d.ts +0 -56
- package/dist/utils/safety-warnings.d.ts.map +0 -1
- package/dist/utils/safety-warnings.js +0 -330
- package/dist/utils/safety-warnings.js.map +0 -1
- package/dist/utils/terminal-controller.d.ts +0 -79
- package/dist/utils/terminal-controller.d.ts.map +0 -1
- package/dist/utils/terminal-controller.js +0 -291
- package/dist/utils/terminal-controller.js.map +0 -1
- package/dist/utils/user-friendly-formatter.d.ts +0 -45
- package/dist/utils/user-friendly-formatter.d.ts.map +0 -1
- package/dist/utils/user-friendly-formatter.js +0 -175
- package/dist/utils/user-friendly-formatter.js.map +0 -1
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GitIssuesTool = void 0;
|
|
4
|
+
const errors_1 = require("../utils/errors");
|
|
5
|
+
class GitIssuesTool {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.name = 'git-issues';
|
|
8
|
+
this.description = 'Issue management for GitHub and Gitea';
|
|
9
|
+
}
|
|
10
|
+
async handle(params, ctx) {
|
|
11
|
+
const action = params.action;
|
|
12
|
+
const provider = params.provider;
|
|
13
|
+
if (!action)
|
|
14
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'action is required');
|
|
15
|
+
if (!provider)
|
|
16
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'provider is required');
|
|
17
|
+
const owner = params.owner;
|
|
18
|
+
const repo = params.repo;
|
|
19
|
+
switch (action) {
|
|
20
|
+
case 'create': {
|
|
21
|
+
if (!params.title)
|
|
22
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'title is required');
|
|
23
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
24
|
+
const result = await ctx.providerManager.github.rest.issues.create({
|
|
25
|
+
owner: owner || process.env.GITHUB_USERNAME,
|
|
26
|
+
repo: repo,
|
|
27
|
+
title: params.title,
|
|
28
|
+
body: params.body,
|
|
29
|
+
labels: params.labels,
|
|
30
|
+
assignees: params.assignees,
|
|
31
|
+
milestone: params.milestone,
|
|
32
|
+
});
|
|
33
|
+
return { success: true, issue: result.data };
|
|
34
|
+
}
|
|
35
|
+
if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
|
|
36
|
+
const axios = require('axios');
|
|
37
|
+
const result = await axios.post(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner || process.env.GITEA_USERNAME}/${repo}/issues`, {
|
|
38
|
+
title: params.title,
|
|
39
|
+
body: params.body,
|
|
40
|
+
labels: params.labels?.map((l) => ({ name: l })),
|
|
41
|
+
assignees: params.assignees,
|
|
42
|
+
}, {
|
|
43
|
+
headers: { Authorization: `token ${ctx.providerManager.giteaToken}` }
|
|
44
|
+
});
|
|
45
|
+
return { success: true, issue: result.data };
|
|
46
|
+
}
|
|
47
|
+
throw new errors_1.MCPError('PROVIDER_NOT_CONFIGURED', `Provider ${provider} is not configured`);
|
|
48
|
+
}
|
|
49
|
+
case 'list': {
|
|
50
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
51
|
+
const result = await ctx.providerManager.github.rest.issues.listForRepo({
|
|
52
|
+
owner: owner || process.env.GITHUB_USERNAME,
|
|
53
|
+
repo: repo,
|
|
54
|
+
state: params.state_filter || 'open',
|
|
55
|
+
sort: params.sort || 'created',
|
|
56
|
+
direction: params.direction || 'desc',
|
|
57
|
+
since: params.since,
|
|
58
|
+
});
|
|
59
|
+
return { success: true, issues: result.data };
|
|
60
|
+
}
|
|
61
|
+
if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
|
|
62
|
+
const axios = require('axios');
|
|
63
|
+
const result = await axios.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner || process.env.GITEA_USERNAME}/${repo}/issues`, {
|
|
64
|
+
params: {
|
|
65
|
+
state: params.state_filter || 'open',
|
|
66
|
+
sort: params.sort || 'created',
|
|
67
|
+
since: params.since,
|
|
68
|
+
},
|
|
69
|
+
headers: { Authorization: `token ${ctx.providerManager.giteaToken}` }
|
|
70
|
+
});
|
|
71
|
+
return { success: true, issues: result.data };
|
|
72
|
+
}
|
|
73
|
+
throw new errors_1.MCPError('PROVIDER_NOT_CONFIGURED', `Provider ${provider} is not configured`);
|
|
74
|
+
}
|
|
75
|
+
case 'get': {
|
|
76
|
+
const issue_number = params.issue_number;
|
|
77
|
+
if (!issue_number)
|
|
78
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'issue_number is required');
|
|
79
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
80
|
+
const result = await ctx.providerManager.github.rest.issues.get({
|
|
81
|
+
owner: owner || process.env.GITHUB_USERNAME,
|
|
82
|
+
repo: repo,
|
|
83
|
+
issue_number,
|
|
84
|
+
});
|
|
85
|
+
return { success: true, issue: result.data };
|
|
86
|
+
}
|
|
87
|
+
if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
|
|
88
|
+
const axios = require('axios');
|
|
89
|
+
const result = await axios.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner || process.env.GITEA_USERNAME}/${repo}/issues/${issue_number}`, {
|
|
90
|
+
headers: { Authorization: `token ${ctx.providerManager.giteaToken}` }
|
|
91
|
+
});
|
|
92
|
+
return { success: true, issue: result.data };
|
|
93
|
+
}
|
|
94
|
+
throw new errors_1.MCPError('PROVIDER_NOT_CONFIGURED', `Provider ${provider} is not configured`);
|
|
95
|
+
}
|
|
96
|
+
case 'update': {
|
|
97
|
+
const issue_number = params.issue_number;
|
|
98
|
+
if (!issue_number)
|
|
99
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'issue_number is required');
|
|
100
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
101
|
+
const result = await ctx.providerManager.github.rest.issues.update({
|
|
102
|
+
owner: owner || process.env.GITHUB_USERNAME,
|
|
103
|
+
repo: repo,
|
|
104
|
+
issue_number,
|
|
105
|
+
title: params.title,
|
|
106
|
+
body: params.body,
|
|
107
|
+
state: params.state,
|
|
108
|
+
labels: params.labels,
|
|
109
|
+
assignees: params.assignees,
|
|
110
|
+
milestone: params.milestone,
|
|
111
|
+
});
|
|
112
|
+
return { success: true, issue: result.data };
|
|
113
|
+
}
|
|
114
|
+
if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
|
|
115
|
+
const axios = require('axios');
|
|
116
|
+
const result = await axios.patch(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner || process.env.GITEA_USERNAME}/${repo}/issues/${issue_number}`, {
|
|
117
|
+
title: params.title,
|
|
118
|
+
body: params.body,
|
|
119
|
+
state: params.state,
|
|
120
|
+
}, {
|
|
121
|
+
headers: { Authorization: `token ${ctx.providerManager.giteaToken}` }
|
|
122
|
+
});
|
|
123
|
+
return { success: true, issue: result.data };
|
|
124
|
+
}
|
|
125
|
+
throw new errors_1.MCPError('PROVIDER_NOT_CONFIGURED', `Provider ${provider} is not configured`);
|
|
126
|
+
}
|
|
127
|
+
case 'close': {
|
|
128
|
+
const issue_number = params.issue_number;
|
|
129
|
+
if (!issue_number)
|
|
130
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'issue_number is required');
|
|
131
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
132
|
+
const result = await ctx.providerManager.github.rest.issues.update({
|
|
133
|
+
owner: owner || process.env.GITHUB_USERNAME,
|
|
134
|
+
repo: repo,
|
|
135
|
+
issue_number,
|
|
136
|
+
state: 'closed',
|
|
137
|
+
});
|
|
138
|
+
return { success: true, issue: result.data };
|
|
139
|
+
}
|
|
140
|
+
if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
|
|
141
|
+
const axios = require('axios');
|
|
142
|
+
const result = await axios.patch(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner || process.env.GITEA_USERNAME}/${repo}/issues/${issue_number}`, { state: 'closed' }, {
|
|
143
|
+
headers: { Authorization: `token ${ctx.providerManager.giteaToken}` }
|
|
144
|
+
});
|
|
145
|
+
return { success: true, issue: result.data };
|
|
146
|
+
}
|
|
147
|
+
throw new errors_1.MCPError('PROVIDER_NOT_CONFIGURED', `Provider ${provider} is not configured`);
|
|
148
|
+
}
|
|
149
|
+
case 'comment': {
|
|
150
|
+
const issue_number = params.issue_number;
|
|
151
|
+
const comment_body = params.comment_body;
|
|
152
|
+
if (!issue_number)
|
|
153
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'issue_number is required');
|
|
154
|
+
if (!comment_body)
|
|
155
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'comment_body is required');
|
|
156
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
157
|
+
const result = await ctx.providerManager.github.rest.issues.createComment({
|
|
158
|
+
owner: owner || process.env.GITHUB_USERNAME,
|
|
159
|
+
repo: repo,
|
|
160
|
+
issue_number,
|
|
161
|
+
body: comment_body,
|
|
162
|
+
});
|
|
163
|
+
return { success: true, comment: result.data };
|
|
164
|
+
}
|
|
165
|
+
if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
|
|
166
|
+
const axios = require('axios');
|
|
167
|
+
const result = await axios.post(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner || process.env.GITEA_USERNAME}/${repo}/issues/${issue_number}/comments`, { body: comment_body }, {
|
|
168
|
+
headers: { Authorization: `token ${ctx.providerManager.giteaToken}` }
|
|
169
|
+
});
|
|
170
|
+
return { success: true, comment: result.data };
|
|
171
|
+
}
|
|
172
|
+
throw new errors_1.MCPError('PROVIDER_NOT_CONFIGURED', `Provider ${provider} is not configured`);
|
|
173
|
+
}
|
|
174
|
+
case 'search': {
|
|
175
|
+
const query = params.query;
|
|
176
|
+
if (!query)
|
|
177
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'query is required');
|
|
178
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
179
|
+
const result = await ctx.providerManager.github.rest.search.issuesAndPullRequests({
|
|
180
|
+
q: `${query} repo:${owner || process.env.GITHUB_USERNAME}/${repo} type:issue`,
|
|
181
|
+
sort: params.search_sort || 'created',
|
|
182
|
+
order: params.search_order || 'desc',
|
|
183
|
+
});
|
|
184
|
+
return { success: true, issues: result.data.items };
|
|
185
|
+
}
|
|
186
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'Search not fully implemented for Gitea');
|
|
187
|
+
}
|
|
188
|
+
default:
|
|
189
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', `Unsupported action: ${action}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
exports.GitIssuesTool = GitIssuesTool;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Tool, MCPContext } from '../types';
|
|
2
|
+
export declare class GitMonitorTool implements Tool {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
handle(params: Record<string, any>, ctx: MCPContext): Promise<{
|
|
6
|
+
success: boolean;
|
|
7
|
+
commits: readonly (import("simple-git").DefaultLogFields & import("simple-git").ListLogLine)[];
|
|
8
|
+
total: number;
|
|
9
|
+
status?: undefined;
|
|
10
|
+
contributors?: undefined;
|
|
11
|
+
} | {
|
|
12
|
+
success: boolean;
|
|
13
|
+
status: import("simple-git").StatusResult | {
|
|
14
|
+
branch: string | null;
|
|
15
|
+
ahead: number;
|
|
16
|
+
behind: number;
|
|
17
|
+
staged: string[];
|
|
18
|
+
modified: string[];
|
|
19
|
+
deleted: string[];
|
|
20
|
+
created: string[];
|
|
21
|
+
renamed: import("simple-git").StatusResultRenamed[];
|
|
22
|
+
conflicted: string[];
|
|
23
|
+
not_added: string[];
|
|
24
|
+
};
|
|
25
|
+
commits?: undefined;
|
|
26
|
+
total?: undefined;
|
|
27
|
+
contributors?: undefined;
|
|
28
|
+
} | {
|
|
29
|
+
success: boolean;
|
|
30
|
+
commits: {
|
|
31
|
+
hash: string;
|
|
32
|
+
date: string;
|
|
33
|
+
message: string;
|
|
34
|
+
author: string;
|
|
35
|
+
email: string;
|
|
36
|
+
}[];
|
|
37
|
+
total?: undefined;
|
|
38
|
+
status?: undefined;
|
|
39
|
+
contributors?: undefined;
|
|
40
|
+
} | {
|
|
41
|
+
success: boolean;
|
|
42
|
+
contributors: {
|
|
43
|
+
name: string;
|
|
44
|
+
email: string;
|
|
45
|
+
commits: number;
|
|
46
|
+
}[];
|
|
47
|
+
commits?: undefined;
|
|
48
|
+
total?: undefined;
|
|
49
|
+
status?: undefined;
|
|
50
|
+
}>;
|
|
51
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GitMonitorTool = void 0;
|
|
7
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
8
|
+
const errors_1 = require("../utils/errors");
|
|
9
|
+
class GitMonitorTool {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.name = 'git-monitor';
|
|
12
|
+
this.description = 'Repository monitoring and status operations';
|
|
13
|
+
}
|
|
14
|
+
async handle(params, ctx) {
|
|
15
|
+
const action = params.action;
|
|
16
|
+
const projectPath = params.projectPath;
|
|
17
|
+
if (!action || !projectPath) {
|
|
18
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'action and projectPath are required');
|
|
19
|
+
}
|
|
20
|
+
const git = (0, simple_git_1.default)({ baseDir: projectPath });
|
|
21
|
+
switch (action) {
|
|
22
|
+
case 'log': {
|
|
23
|
+
const options = {
|
|
24
|
+
maxCount: params.limit || 10,
|
|
25
|
+
};
|
|
26
|
+
if (params.since)
|
|
27
|
+
options.from = params.since;
|
|
28
|
+
if (params.until)
|
|
29
|
+
options.to = params.until;
|
|
30
|
+
if (params.author)
|
|
31
|
+
options.author = params.author;
|
|
32
|
+
const log = await git.log(options);
|
|
33
|
+
return {
|
|
34
|
+
success: true,
|
|
35
|
+
commits: log.all,
|
|
36
|
+
total: log.total,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
case 'status': {
|
|
40
|
+
const status = await git.status();
|
|
41
|
+
const detailed = params.detailed ? {
|
|
42
|
+
branch: status.current,
|
|
43
|
+
ahead: status.ahead,
|
|
44
|
+
behind: status.behind,
|
|
45
|
+
staged: status.staged,
|
|
46
|
+
modified: status.modified,
|
|
47
|
+
deleted: status.deleted,
|
|
48
|
+
created: status.created,
|
|
49
|
+
renamed: status.renamed,
|
|
50
|
+
conflicted: status.conflicted,
|
|
51
|
+
not_added: status.not_added,
|
|
52
|
+
} : status;
|
|
53
|
+
return { success: true, status: detailed };
|
|
54
|
+
}
|
|
55
|
+
case 'commits': {
|
|
56
|
+
const branch = params.branch;
|
|
57
|
+
const options = {
|
|
58
|
+
maxCount: params.limit || 50,
|
|
59
|
+
};
|
|
60
|
+
if (branch)
|
|
61
|
+
options.from = branch;
|
|
62
|
+
if (params.since)
|
|
63
|
+
options.from = params.since;
|
|
64
|
+
if (params.author)
|
|
65
|
+
options.author = params.author;
|
|
66
|
+
const log = await git.log(options);
|
|
67
|
+
return {
|
|
68
|
+
success: true,
|
|
69
|
+
commits: log.all.map(c => ({
|
|
70
|
+
hash: c.hash,
|
|
71
|
+
date: c.date,
|
|
72
|
+
message: c.message,
|
|
73
|
+
author: c.author_name,
|
|
74
|
+
email: c.author_email,
|
|
75
|
+
})),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
case 'contributors': {
|
|
79
|
+
const log = await git.log();
|
|
80
|
+
const contributors = new Map();
|
|
81
|
+
log.all.forEach(commit => {
|
|
82
|
+
const key = commit.author_email;
|
|
83
|
+
if (contributors.has(key)) {
|
|
84
|
+
contributors.get(key).commits++;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
contributors.set(key, {
|
|
88
|
+
name: commit.author_name,
|
|
89
|
+
email: commit.author_email,
|
|
90
|
+
commits: 1,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const sorted = Array.from(contributors.values()).sort((a, b) => b.commits - a.commits);
|
|
95
|
+
return { success: true, contributors: sorted };
|
|
96
|
+
}
|
|
97
|
+
default:
|
|
98
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', `Unsupported action: ${action}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.GitMonitorTool = GitMonitorTool;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GitPackagesTool = void 0;
|
|
4
|
+
const errors_1 = require("../utils/errors");
|
|
5
|
+
class GitPackagesTool {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.name = 'git-packages';
|
|
8
|
+
this.description = 'Package management operations';
|
|
9
|
+
}
|
|
10
|
+
async handle(params, ctx) {
|
|
11
|
+
const action = params.action;
|
|
12
|
+
if (!action)
|
|
13
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'action is required');
|
|
14
|
+
switch (action) {
|
|
15
|
+
case 'list':
|
|
16
|
+
case 'get':
|
|
17
|
+
case 'create':
|
|
18
|
+
case 'update':
|
|
19
|
+
case 'delete':
|
|
20
|
+
case 'publish':
|
|
21
|
+
case 'download':
|
|
22
|
+
throw new errors_1.MCPError('NOT_IMPLEMENTED', `Action ${action} not yet fully implemented`);
|
|
23
|
+
default:
|
|
24
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', `Unsupported action: ${action}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.GitPackagesTool = GitPackagesTool;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Tool, MCPContext } from '../types';
|
|
2
|
+
export declare class GitPullsTool implements Tool {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
handle(params: Record<string, any>, ctx: MCPContext): Promise<{
|
|
6
|
+
success: boolean;
|
|
7
|
+
pull: any;
|
|
8
|
+
pulls?: undefined;
|
|
9
|
+
merged?: undefined;
|
|
10
|
+
review?: undefined;
|
|
11
|
+
} | {
|
|
12
|
+
success: boolean;
|
|
13
|
+
pulls: any;
|
|
14
|
+
pull?: undefined;
|
|
15
|
+
merged?: undefined;
|
|
16
|
+
review?: undefined;
|
|
17
|
+
} | {
|
|
18
|
+
success: boolean;
|
|
19
|
+
merged: any;
|
|
20
|
+
pull?: undefined;
|
|
21
|
+
pulls?: undefined;
|
|
22
|
+
review?: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
success: boolean;
|
|
25
|
+
review: {
|
|
26
|
+
id: number;
|
|
27
|
+
node_id: string;
|
|
28
|
+
user: {
|
|
29
|
+
name?: string | null;
|
|
30
|
+
email?: string | null;
|
|
31
|
+
login: string;
|
|
32
|
+
id: number;
|
|
33
|
+
node_id: string;
|
|
34
|
+
avatar_url: string;
|
|
35
|
+
gravatar_id: string | null;
|
|
36
|
+
url: string;
|
|
37
|
+
html_url: string;
|
|
38
|
+
followers_url: string;
|
|
39
|
+
following_url: string;
|
|
40
|
+
gists_url: string;
|
|
41
|
+
starred_url: string;
|
|
42
|
+
subscriptions_url: string;
|
|
43
|
+
organizations_url: string;
|
|
44
|
+
repos_url: string;
|
|
45
|
+
events_url: string;
|
|
46
|
+
received_events_url: string;
|
|
47
|
+
type: string;
|
|
48
|
+
site_admin: boolean;
|
|
49
|
+
starred_at?: string;
|
|
50
|
+
user_view_type?: string;
|
|
51
|
+
} | null;
|
|
52
|
+
body: string;
|
|
53
|
+
state: string;
|
|
54
|
+
html_url: string;
|
|
55
|
+
pull_request_url: string;
|
|
56
|
+
_links: {
|
|
57
|
+
html: {
|
|
58
|
+
href: string;
|
|
59
|
+
};
|
|
60
|
+
pull_request: {
|
|
61
|
+
href: string;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
submitted_at?: string;
|
|
65
|
+
commit_id: string | null;
|
|
66
|
+
body_html?: string;
|
|
67
|
+
body_text?: string;
|
|
68
|
+
author_association: "COLLABORATOR" | "CONTRIBUTOR" | "FIRST_TIMER" | "FIRST_TIME_CONTRIBUTOR" | "MANNEQUIN" | "MEMBER" | "NONE" | "OWNER";
|
|
69
|
+
};
|
|
70
|
+
pull?: undefined;
|
|
71
|
+
pulls?: undefined;
|
|
72
|
+
merged?: undefined;
|
|
73
|
+
}>;
|
|
74
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GitPullsTool = void 0;
|
|
7
|
+
const errors_1 = require("../utils/errors");
|
|
8
|
+
const axios_1 = __importDefault(require("axios"));
|
|
9
|
+
class GitPullsTool {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.name = 'git-pulls';
|
|
12
|
+
this.description = 'Pull request management for GitHub and Gitea';
|
|
13
|
+
}
|
|
14
|
+
async handle(params, ctx) {
|
|
15
|
+
const action = params.action;
|
|
16
|
+
const provider = params.provider;
|
|
17
|
+
if (!action)
|
|
18
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'action is required');
|
|
19
|
+
if (!provider)
|
|
20
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'provider is required');
|
|
21
|
+
const owner = params.owner || process.env.GITHUB_USERNAME || process.env.GITEA_USERNAME;
|
|
22
|
+
const repo = params.repo;
|
|
23
|
+
switch (action) {
|
|
24
|
+
case 'create': {
|
|
25
|
+
if (!params.title || !params.head || !params.base) {
|
|
26
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'title, head, and base are required');
|
|
27
|
+
}
|
|
28
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
29
|
+
const result = await ctx.providerManager.github.rest.pulls.create({
|
|
30
|
+
owner: owner,
|
|
31
|
+
repo: repo,
|
|
32
|
+
title: params.title,
|
|
33
|
+
head: params.head,
|
|
34
|
+
base: params.base,
|
|
35
|
+
body: params.body,
|
|
36
|
+
});
|
|
37
|
+
return { success: true, pull: result.data };
|
|
38
|
+
}
|
|
39
|
+
if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
|
|
40
|
+
const result = await axios_1.default.post(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner}/${repo}/pulls`, {
|
|
41
|
+
title: params.title,
|
|
42
|
+
head: params.head,
|
|
43
|
+
base: params.base,
|
|
44
|
+
body: params.body,
|
|
45
|
+
}, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
46
|
+
return { success: true, pull: result.data };
|
|
47
|
+
}
|
|
48
|
+
throw new errors_1.MCPError('PROVIDER_NOT_CONFIGURED', `Provider ${provider} is not configured`);
|
|
49
|
+
}
|
|
50
|
+
case 'list': {
|
|
51
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
52
|
+
const result = await ctx.providerManager.github.rest.pulls.list({
|
|
53
|
+
owner: owner,
|
|
54
|
+
repo: repo,
|
|
55
|
+
state: params.state_filter || 'open',
|
|
56
|
+
sort: params.sort || 'created',
|
|
57
|
+
direction: params.direction || 'desc',
|
|
58
|
+
});
|
|
59
|
+
return { success: true, pulls: result.data };
|
|
60
|
+
}
|
|
61
|
+
if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
|
|
62
|
+
const result = await axios_1.default.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner}/${repo}/pulls`, {
|
|
63
|
+
params: { state: params.state_filter || 'open' },
|
|
64
|
+
headers: { Authorization: `token ${ctx.providerManager.giteaToken}` }
|
|
65
|
+
});
|
|
66
|
+
return { success: true, pulls: result.data };
|
|
67
|
+
}
|
|
68
|
+
throw new errors_1.MCPError('PROVIDER_NOT_CONFIGURED', `Provider ${provider} is not configured`);
|
|
69
|
+
}
|
|
70
|
+
case 'get': {
|
|
71
|
+
const pull_number = params.pull_number;
|
|
72
|
+
if (!pull_number)
|
|
73
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'pull_number is required');
|
|
74
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
75
|
+
const result = await ctx.providerManager.github.rest.pulls.get({
|
|
76
|
+
owner: owner,
|
|
77
|
+
repo: repo,
|
|
78
|
+
pull_number,
|
|
79
|
+
});
|
|
80
|
+
return { success: true, pull: result.data };
|
|
81
|
+
}
|
|
82
|
+
if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
|
|
83
|
+
const result = await axios_1.default.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner}/${repo}/pulls/${pull_number}`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
84
|
+
return { success: true, pull: result.data };
|
|
85
|
+
}
|
|
86
|
+
throw new errors_1.MCPError('PROVIDER_NOT_CONFIGURED', `Provider ${provider} is not configured`);
|
|
87
|
+
}
|
|
88
|
+
case 'update': {
|
|
89
|
+
const pull_number = params.pull_number;
|
|
90
|
+
if (!pull_number)
|
|
91
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'pull_number is required');
|
|
92
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
93
|
+
const result = await ctx.providerManager.github.rest.pulls.update({
|
|
94
|
+
owner: owner,
|
|
95
|
+
repo: repo,
|
|
96
|
+
pull_number,
|
|
97
|
+
title: params.title,
|
|
98
|
+
body: params.body,
|
|
99
|
+
state: params.state,
|
|
100
|
+
});
|
|
101
|
+
return { success: true, pull: result.data };
|
|
102
|
+
}
|
|
103
|
+
if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
|
|
104
|
+
const result = await axios_1.default.patch(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner}/${repo}/pulls/${pull_number}`, { title: params.title, body: params.body }, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
105
|
+
return { success: true, pull: result.data };
|
|
106
|
+
}
|
|
107
|
+
throw new errors_1.MCPError('PROVIDER_NOT_CONFIGURED', `Provider ${provider} is not configured`);
|
|
108
|
+
}
|
|
109
|
+
case 'merge': {
|
|
110
|
+
const pull_number = params.pull_number;
|
|
111
|
+
if (!pull_number)
|
|
112
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'pull_number is required');
|
|
113
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
114
|
+
const result = await ctx.providerManager.github.rest.pulls.merge({
|
|
115
|
+
owner: owner,
|
|
116
|
+
repo: repo,
|
|
117
|
+
pull_number,
|
|
118
|
+
commit_title: params.commit_title,
|
|
119
|
+
commit_message: params.commit_message,
|
|
120
|
+
merge_method: params.merge_method || 'merge',
|
|
121
|
+
});
|
|
122
|
+
return { success: true, merged: result.data };
|
|
123
|
+
}
|
|
124
|
+
if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
|
|
125
|
+
const result = await axios_1.default.post(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner}/${repo}/pulls/${pull_number}/merge`, {
|
|
126
|
+
Do: params.merge_method || 'merge',
|
|
127
|
+
MergeTitleField: params.commit_title,
|
|
128
|
+
MergeMessageField: params.commit_message,
|
|
129
|
+
}, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
130
|
+
return { success: true, merged: result.data };
|
|
131
|
+
}
|
|
132
|
+
throw new errors_1.MCPError('PROVIDER_NOT_CONFIGURED', `Provider ${provider} is not configured`);
|
|
133
|
+
}
|
|
134
|
+
case 'close': {
|
|
135
|
+
const pull_number = params.pull_number;
|
|
136
|
+
if (!pull_number)
|
|
137
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'pull_number is required');
|
|
138
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
139
|
+
const result = await ctx.providerManager.github.rest.pulls.update({
|
|
140
|
+
owner: owner,
|
|
141
|
+
repo: repo,
|
|
142
|
+
pull_number,
|
|
143
|
+
state: 'closed',
|
|
144
|
+
});
|
|
145
|
+
return { success: true, pull: result.data };
|
|
146
|
+
}
|
|
147
|
+
if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
|
|
148
|
+
const result = await axios_1.default.patch(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner}/${repo}/pulls/${pull_number}`, { state: 'closed' }, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
149
|
+
return { success: true, pull: result.data };
|
|
150
|
+
}
|
|
151
|
+
throw new errors_1.MCPError('PROVIDER_NOT_CONFIGURED', `Provider ${provider} is not configured`);
|
|
152
|
+
}
|
|
153
|
+
case 'review': {
|
|
154
|
+
const pull_number = params.pull_number;
|
|
155
|
+
const event = params.event;
|
|
156
|
+
if (!pull_number || !event) {
|
|
157
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'pull_number and event are required');
|
|
158
|
+
}
|
|
159
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
160
|
+
const result = await ctx.providerManager.github.rest.pulls.createReview({
|
|
161
|
+
owner: owner,
|
|
162
|
+
repo: repo,
|
|
163
|
+
pull_number,
|
|
164
|
+
event,
|
|
165
|
+
body: params.review_body,
|
|
166
|
+
});
|
|
167
|
+
return { success: true, review: result.data };
|
|
168
|
+
}
|
|
169
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'Review not fully implemented for Gitea');
|
|
170
|
+
}
|
|
171
|
+
case 'search': {
|
|
172
|
+
const query = params.query;
|
|
173
|
+
if (!query)
|
|
174
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'query is required');
|
|
175
|
+
if (provider === 'github' && ctx.providerManager.github) {
|
|
176
|
+
const result = await ctx.providerManager.github.rest.search.issuesAndPullRequests({
|
|
177
|
+
q: `${query} repo:${owner}/${repo} type:pr`,
|
|
178
|
+
sort: params.search_sort || 'created',
|
|
179
|
+
order: params.search_order || 'desc',
|
|
180
|
+
});
|
|
181
|
+
return { success: true, pulls: result.data.items };
|
|
182
|
+
}
|
|
183
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'Search not fully implemented for Gitea');
|
|
184
|
+
}
|
|
185
|
+
default:
|
|
186
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', `Unsupported action: ${action}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
exports.GitPullsTool = GitPullsTool;
|