@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.
Files changed (224) hide show
  1. package/README.md +25 -0
  2. package/dist/config.d.ts +5 -131
  3. package/dist/config.js +28 -430
  4. package/dist/index.d.ts +1 -21
  5. package/dist/index.js +66 -144
  6. package/dist/providers/giteaProvider.d.ts +3 -0
  7. package/dist/providers/giteaProvider.js +12 -0
  8. package/dist/providers/githubProvider.d.ts +2 -0
  9. package/dist/providers/githubProvider.js +7 -0
  10. package/dist/providers/providerManager.d.ts +11 -0
  11. package/dist/providers/providerManager.js +48 -0
  12. package/dist/server.d.ts +6 -40
  13. package/dist/server.js +30 -700
  14. package/dist/tools/gitAnalytics.d.ts +29 -0
  15. package/dist/tools/gitAnalytics.js +72 -0
  16. package/dist/tools/gitArchive.d.ts +6 -0
  17. package/dist/tools/gitArchive.js +27 -0
  18. package/dist/tools/gitBackup.d.ts +10 -0
  19. package/dist/tools/gitBackup.js +44 -0
  20. package/dist/tools/gitBranches.d.ts +72 -0
  21. package/dist/tools/gitBranches.js +97 -0
  22. package/dist/tools/gitConfig.d.ts +34 -0
  23. package/dist/tools/gitConfig.js +73 -0
  24. package/dist/tools/gitFiles.d.ts +24 -0
  25. package/dist/tools/gitFiles.js +53 -0
  26. package/dist/tools/gitIssues.d.ts +21 -0
  27. package/dist/tools/gitIssues.js +193 -0
  28. package/dist/tools/gitMonitor.d.ts +51 -0
  29. package/dist/tools/gitMonitor.js +102 -0
  30. package/dist/tools/gitPackages.d.ts +6 -0
  31. package/dist/tools/gitPackages.js +28 -0
  32. package/dist/tools/gitPulls.d.ts +74 -0
  33. package/dist/tools/gitPulls.js +190 -0
  34. package/dist/tools/gitRelease.d.ts +34 -0
  35. package/dist/tools/gitRelease.js +99 -0
  36. package/dist/tools/gitRemote.d.ts +51 -0
  37. package/dist/tools/gitRemote.js +68 -0
  38. package/dist/tools/gitReset.d.ts +34 -0
  39. package/dist/tools/gitReset.js +64 -0
  40. package/dist/tools/gitStash.d.ts +41 -0
  41. package/dist/tools/gitStash.js +67 -0
  42. package/dist/tools/gitSync.d.ts +25 -0
  43. package/dist/tools/gitSync.js +51 -0
  44. package/dist/tools/gitTags.d.ts +30 -0
  45. package/dist/tools/gitTags.js +69 -0
  46. package/dist/tools/gitWorkflow.d.ts +69 -0
  47. package/dist/tools/gitWorkflow.js +129 -0
  48. package/dist/types.d.ts +10 -0
  49. package/dist/types.js +2 -0
  50. package/dist/utils/errors.d.ts +13 -0
  51. package/dist/utils/errors.js +22 -0
  52. package/dist/utils/safetyController.d.ts +1 -0
  53. package/dist/utils/safetyController.js +15 -0
  54. package/package.json +7 -2
  55. package/dist/config.d.ts.map +0 -1
  56. package/dist/config.js.map +0 -1
  57. package/dist/index.d.ts.map +0 -1
  58. package/dist/index.js.map +0 -1
  59. package/dist/providers/base-provider.d.ts +0 -66
  60. package/dist/providers/base-provider.d.ts.map +0 -1
  61. package/dist/providers/base-provider.js +0 -65
  62. package/dist/providers/base-provider.js.map +0 -1
  63. package/dist/providers/gitea-provider.d.ts +0 -79
  64. package/dist/providers/gitea-provider.d.ts.map +0 -1
  65. package/dist/providers/gitea-provider.js +0 -576
  66. package/dist/providers/gitea-provider.js.map +0 -1
  67. package/dist/providers/github-provider.d.ts +0 -74
  68. package/dist/providers/github-provider.d.ts.map +0 -1
  69. package/dist/providers/github-provider.js +0 -683
  70. package/dist/providers/github-provider.js.map +0 -1
  71. package/dist/providers/index.d.ts +0 -13
  72. package/dist/providers/index.d.ts.map +0 -1
  73. package/dist/providers/index.js +0 -35
  74. package/dist/providers/index.js.map +0 -1
  75. package/dist/providers/provider-factory.d.ts +0 -49
  76. package/dist/providers/provider-factory.d.ts.map +0 -1
  77. package/dist/providers/provider-factory.js +0 -193
  78. package/dist/providers/provider-factory.js.map +0 -1
  79. package/dist/providers/provider-operation-handler.d.ts +0 -115
  80. package/dist/providers/provider-operation-handler.d.ts.map +0 -1
  81. package/dist/providers/provider-operation-handler.js +0 -449
  82. package/dist/providers/provider-operation-handler.js.map +0 -1
  83. package/dist/providers/types.d.ts +0 -200
  84. package/dist/providers/types.d.ts.map +0 -1
  85. package/dist/providers/types.js +0 -8
  86. package/dist/providers/types.js.map +0 -1
  87. package/dist/server.d.ts.map +0 -1
  88. package/dist/server.js.map +0 -1
  89. package/dist/tools/git-analytics.d.ts +0 -237
  90. package/dist/tools/git-analytics.d.ts.map +0 -1
  91. package/dist/tools/git-analytics.js +0 -828
  92. package/dist/tools/git-analytics.js.map +0 -1
  93. package/dist/tools/git-archive.d.ts +0 -113
  94. package/dist/tools/git-archive.d.ts.map +0 -1
  95. package/dist/tools/git-archive.js +0 -466
  96. package/dist/tools/git-archive.js.map +0 -1
  97. package/dist/tools/git-auto-monitor.d.ts +0 -180
  98. package/dist/tools/git-auto-monitor.d.ts.map +0 -1
  99. package/dist/tools/git-auto-monitor.js +0 -522
  100. package/dist/tools/git-auto-monitor.js.map +0 -1
  101. package/dist/tools/git-backup.d.ts +0 -105
  102. package/dist/tools/git-backup.d.ts.map +0 -1
  103. package/dist/tools/git-backup.js +0 -414
  104. package/dist/tools/git-backup.js.map +0 -1
  105. package/dist/tools/git-branches.d.ts +0 -183
  106. package/dist/tools/git-branches.d.ts.map +0 -1
  107. package/dist/tools/git-branches.js +0 -507
  108. package/dist/tools/git-branches.js.map +0 -1
  109. package/dist/tools/git-config.d.ts +0 -119
  110. package/dist/tools/git-config.d.ts.map +0 -1
  111. package/dist/tools/git-config.js +0 -449
  112. package/dist/tools/git-config.js.map +0 -1
  113. package/dist/tools/git-files.d.ts +0 -150
  114. package/dist/tools/git-files.d.ts.map +0 -1
  115. package/dist/tools/git-files.js +0 -536
  116. package/dist/tools/git-files.js.map +0 -1
  117. package/dist/tools/git-history.d.ts +0 -253
  118. package/dist/tools/git-history.d.ts.map +0 -1
  119. package/dist/tools/git-history.js +0 -824
  120. package/dist/tools/git-history.js.map +0 -1
  121. package/dist/tools/git-issues.d.ts +0 -164
  122. package/dist/tools/git-issues.d.ts.map +0 -1
  123. package/dist/tools/git-issues.js +0 -349
  124. package/dist/tools/git-issues.js.map +0 -1
  125. package/dist/tools/git-monitor.d.ts +0 -154
  126. package/dist/tools/git-monitor.d.ts.map +0 -1
  127. package/dist/tools/git-monitor.js +0 -531
  128. package/dist/tools/git-monitor.js.map +0 -1
  129. package/dist/tools/git-packages.d.ts +0 -157
  130. package/dist/tools/git-packages.d.ts.map +0 -1
  131. package/dist/tools/git-packages.js +0 -534
  132. package/dist/tools/git-packages.js.map +0 -1
  133. package/dist/tools/git-pulls.d.ts +0 -180
  134. package/dist/tools/git-pulls.d.ts.map +0 -1
  135. package/dist/tools/git-pulls.js +0 -378
  136. package/dist/tools/git-pulls.js.map +0 -1
  137. package/dist/tools/git-release.d.ts +0 -161
  138. package/dist/tools/git-release.d.ts.map +0 -1
  139. package/dist/tools/git-release.js +0 -466
  140. package/dist/tools/git-release.js.map +0 -1
  141. package/dist/tools/git-remote.d.ts +0 -128
  142. package/dist/tools/git-remote.d.ts.map +0 -1
  143. package/dist/tools/git-remote.js +0 -542
  144. package/dist/tools/git-remote.js.map +0 -1
  145. package/dist/tools/git-reset.d.ts +0 -120
  146. package/dist/tools/git-reset.d.ts.map +0 -1
  147. package/dist/tools/git-reset.js +0 -479
  148. package/dist/tools/git-reset.js.map +0 -1
  149. package/dist/tools/git-stash.d.ts +0 -124
  150. package/dist/tools/git-stash.d.ts.map +0 -1
  151. package/dist/tools/git-stash.js +0 -506
  152. package/dist/tools/git-stash.js.map +0 -1
  153. package/dist/tools/git-sync.d.ts +0 -154
  154. package/dist/tools/git-sync.d.ts.map +0 -1
  155. package/dist/tools/git-sync.js +0 -479
  156. package/dist/tools/git-sync.js.map +0 -1
  157. package/dist/tools/git-tags.d.ts +0 -136
  158. package/dist/tools/git-tags.d.ts.map +0 -1
  159. package/dist/tools/git-tags.js +0 -470
  160. package/dist/tools/git-tags.js.map +0 -1
  161. package/dist/tools/git-update.d.ts +0 -224
  162. package/dist/tools/git-update.d.ts.map +0 -1
  163. package/dist/tools/git-update.js +0 -948
  164. package/dist/tools/git-update.js.map +0 -1
  165. package/dist/tools/git-workflow.d.ts +0 -189
  166. package/dist/tools/git-workflow.d.ts.map +0 -1
  167. package/dist/tools/git-workflow.js +0 -551
  168. package/dist/tools/git-workflow.js.map +0 -1
  169. package/dist/utils/credential-manager.d.ts +0 -119
  170. package/dist/utils/credential-manager.d.ts.map +0 -1
  171. package/dist/utils/credential-manager.js +0 -450
  172. package/dist/utils/credential-manager.js.map +0 -1
  173. package/dist/utils/data-merger.d.ts +0 -49
  174. package/dist/utils/data-merger.d.ts.map +0 -1
  175. package/dist/utils/data-merger.js +0 -233
  176. package/dist/utils/data-merger.js.map +0 -1
  177. package/dist/utils/git-command-executor.d.ts +0 -330
  178. package/dist/utils/git-command-executor.d.ts.map +0 -1
  179. package/dist/utils/git-command-executor.js +0 -901
  180. package/dist/utils/git-command-executor.js.map +0 -1
  181. package/dist/utils/logger.d.ts +0 -143
  182. package/dist/utils/logger.d.ts.map +0 -1
  183. package/dist/utils/logger.js +0 -473
  184. package/dist/utils/logger.js.map +0 -1
  185. package/dist/utils/operation-error-handler.d.ts +0 -97
  186. package/dist/utils/operation-error-handler.d.ts.map +0 -1
  187. package/dist/utils/operation-error-handler.js +0 -367
  188. package/dist/utils/operation-error-handler.js.map +0 -1
  189. package/dist/utils/parameter-validator.d.ts +0 -49
  190. package/dist/utils/parameter-validator.d.ts.map +0 -1
  191. package/dist/utils/parameter-validator.js +0 -647
  192. package/dist/utils/parameter-validator.js.map +0 -1
  193. package/dist/utils/repository-checker.d.ts +0 -46
  194. package/dist/utils/repository-checker.d.ts.map +0 -1
  195. package/dist/utils/repository-checker.js +0 -151
  196. package/dist/utils/repository-checker.js.map +0 -1
  197. package/dist/utils/repository-detector.d.ts +0 -128
  198. package/dist/utils/repository-detector.d.ts.map +0 -1
  199. package/dist/utils/repository-detector.js +0 -422
  200. package/dist/utils/repository-detector.js.map +0 -1
  201. package/dist/utils/repository-sync.d.ts +0 -67
  202. package/dist/utils/repository-sync.d.ts.map +0 -1
  203. package/dist/utils/repository-sync.js +0 -344
  204. package/dist/utils/repository-sync.js.map +0 -1
  205. package/dist/utils/response-formatter.d.ts +0 -146
  206. package/dist/utils/response-formatter.d.ts.map +0 -1
  207. package/dist/utils/response-formatter.js +0 -378
  208. package/dist/utils/response-formatter.js.map +0 -1
  209. package/dist/utils/retry.d.ts +0 -12
  210. package/dist/utils/retry.d.ts.map +0 -1
  211. package/dist/utils/retry.js +0 -28
  212. package/dist/utils/retry.js.map +0 -1
  213. package/dist/utils/safety-warnings.d.ts +0 -56
  214. package/dist/utils/safety-warnings.d.ts.map +0 -1
  215. package/dist/utils/safety-warnings.js +0 -330
  216. package/dist/utils/safety-warnings.js.map +0 -1
  217. package/dist/utils/terminal-controller.d.ts +0 -79
  218. package/dist/utils/terminal-controller.d.ts.map +0 -1
  219. package/dist/utils/terminal-controller.js +0 -291
  220. package/dist/utils/terminal-controller.js.map +0 -1
  221. package/dist/utils/user-friendly-formatter.d.ts +0 -45
  222. package/dist/utils/user-friendly-formatter.d.ts.map +0 -1
  223. package/dist/utils/user-friendly-formatter.js +0 -175
  224. package/dist/utils/user-friendly-formatter.js.map +0 -1
@@ -1,824 +0,0 @@
1
- "use strict";
2
- /**
3
- * Git History Tool
4
- *
5
- * Comprehensive change tracking tool that records all repository modifications
6
- * with detailed timestamps, storing history locally in JSON and syncing to remote providers.
7
- *
8
- * Operations: log, track, sync, export, auto
9
- */
10
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- var desc = Object.getOwnPropertyDescriptor(m, k);
13
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
- desc = { enumerable: true, get: function() { return m[k]; } };
15
- }
16
- Object.defineProperty(o, k2, desc);
17
- }) : (function(o, m, k, k2) {
18
- if (k2 === undefined) k2 = k;
19
- o[k2] = m[k];
20
- }));
21
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
- Object.defineProperty(o, "default", { enumerable: true, value: v });
23
- }) : function(o, v) {
24
- o["default"] = v;
25
- });
26
- var __importStar = (this && this.__importStar) || (function () {
27
- var ownKeys = function(o) {
28
- ownKeys = Object.getOwnPropertyNames || function (o) {
29
- var ar = [];
30
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
- return ar;
32
- };
33
- return ownKeys(o);
34
- };
35
- return function (mod) {
36
- if (mod && mod.__esModule) return mod;
37
- var result = {};
38
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
- __setModuleDefault(result, mod);
40
- return result;
41
- };
42
- })();
43
- Object.defineProperty(exports, "__esModule", { value: true });
44
- exports.GitHistoryTool = void 0;
45
- const git_command_executor_js_1 = require("../utils/git-command-executor.js");
46
- const parameter_validator_js_1 = require("../utils/parameter-validator.js");
47
- const operation_error_handler_js_1 = require("../utils/operation-error-handler.js");
48
- const provider_operation_handler_js_1 = require("../providers/provider-operation-handler.js");
49
- const fs = __importStar(require("fs"));
50
- const path = __importStar(require("path"));
51
- class GitHistoryTool {
52
- gitExecutor;
53
- providerHandler;
54
- historyPath;
55
- configPath;
56
- constructor(providerConfig) {
57
- this.gitExecutor = new git_command_executor_js_1.GitCommandExecutor();
58
- this.historyPath = path.join('.git-history', 'history.json');
59
- this.configPath = path.join('.git-history', 'config.json');
60
- if (providerConfig) {
61
- this.providerHandler = new provider_operation_handler_js_1.ProviderOperationHandler(providerConfig);
62
- }
63
- this.ensureHistoryDirectory();
64
- }
65
- /**
66
- * Execute git-history operation
67
- */
68
- async execute(params) {
69
- const startTime = Date.now();
70
- try {
71
- // Validate basic parameters
72
- const validation = parameter_validator_js_1.ParameterValidator.validateToolParams('git-history', params);
73
- if (!validation.isValid) {
74
- return operation_error_handler_js_1.OperationErrorHandler.createToolError('VALIDATION_ERROR', `Parameter validation failed: ${validation.errors.join(', ')}`, params.action, { validationErrors: validation.errors }, validation.suggestions);
75
- }
76
- // Validate operation-specific parameters
77
- const operationValidation = this.validateOperationParams(params);
78
- if (!operationValidation.isValid) {
79
- return operation_error_handler_js_1.OperationErrorHandler.createToolError('VALIDATION_ERROR', `Operation validation failed: ${operationValidation.errors.join(', ')}`, params.action, { validationErrors: operationValidation.errors }, operationValidation.suggestions);
80
- }
81
- // Route to appropriate handler
82
- switch (params.action) {
83
- case 'log':
84
- return await this.handleLog(params, startTime);
85
- case 'track':
86
- return await this.handleTrack(params, startTime);
87
- case 'sync':
88
- return await this.handleSync(params, startTime);
89
- case 'export':
90
- return await this.handleExport(params, startTime);
91
- case 'auto':
92
- return await this.handleAuto(params, startTime);
93
- default:
94
- return operation_error_handler_js_1.OperationErrorHandler.createToolError('UNSUPPORTED_OPERATION', `Unsupported operation: ${params.action}`, params.action, { supportedOperations: ['log', 'track', 'sync', 'export', 'auto'] }, ['Use one of the supported operations: log, track, sync, export, auto']);
95
- }
96
- }
97
- catch (error) {
98
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
99
- return operation_error_handler_js_1.OperationErrorHandler.createToolError('EXECUTION_ERROR', `Failed to execute git-history operation: ${errorMessage}`, params.action, { error: errorMessage });
100
- }
101
- }
102
- /**
103
- * Validate operation-specific parameters
104
- */
105
- validateOperationParams(params) {
106
- const errors = [];
107
- const suggestions = [];
108
- switch (params.action) {
109
- case 'track':
110
- if (!params.message) {
111
- errors.push('Message is required for track operation');
112
- suggestions.push('Provide a message describing the change');
113
- }
114
- break;
115
- case 'sync':
116
- if (!this.providerHandler && params.syncMethod === 'api') {
117
- errors.push('Provider configuration required for API sync');
118
- suggestions.push('Configure GitHub/Gitea provider or use file sync method');
119
- }
120
- break;
121
- case 'export':
122
- if (params.outputPath && !path.isAbsolute(params.outputPath)) {
123
- errors.push('Output path must be absolute');
124
- suggestions.push('Provide an absolute path for export file');
125
- }
126
- break;
127
- }
128
- return {
129
- isValid: errors.length === 0,
130
- errors,
131
- suggestions
132
- };
133
- }
134
- /**
135
- * Handle log operation - View history entries
136
- */
137
- async handleLog(params, startTime) {
138
- try {
139
- const history = await this.loadHistory();
140
- let entries = [...history.entries];
141
- // Apply filters
142
- if (params.since) {
143
- const sinceDate = new Date(params.since);
144
- entries = entries.filter(entry => new Date(entry.timestamp) >= sinceDate);
145
- }
146
- if (params.until) {
147
- const untilDate = new Date(params.until);
148
- entries = entries.filter(entry => new Date(entry.timestamp) <= untilDate);
149
- }
150
- if (params.author) {
151
- entries = entries.filter(entry => entry.author.toLowerCase().includes(params.author.toLowerCase()) ||
152
- entry.authorEmail.toLowerCase().includes(params.author.toLowerCase()));
153
- }
154
- if (params.filePath) {
155
- entries = entries.filter(entry => entry.filesChanged.some(file => file.path.includes(params.filePath)));
156
- }
157
- if (params.branch) {
158
- entries = entries.filter(entry => entry.branch === params.branch);
159
- }
160
- // Sort by timestamp (newest first)
161
- entries.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
162
- // Apply limit
163
- const limit = params.limit || 50;
164
- entries = entries.slice(0, limit);
165
- // Format output
166
- const format = params.format || 'json';
167
- let formattedData;
168
- if (format === 'markdown') {
169
- formattedData = this.formatHistoryAsMarkdown(entries);
170
- }
171
- else {
172
- formattedData = {
173
- totalEntries: history.entries.length,
174
- filteredEntries: entries.length,
175
- entries: entries
176
- };
177
- }
178
- return {
179
- success: true,
180
- data: {
181
- ...formattedData,
182
- filters: {
183
- since: params.since,
184
- until: params.until,
185
- author: params.author,
186
- filePath: params.filePath,
187
- branch: params.branch,
188
- limit: limit
189
- }
190
- },
191
- metadata: {
192
- operation: params.action,
193
- executionTime: Date.now() - startTime,
194
- timestamp: new Date().toISOString()
195
- }
196
- };
197
- }
198
- catch (error) {
199
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
200
- return operation_error_handler_js_1.OperationErrorHandler.createToolError('LOG_FAILED', `Failed to retrieve history: ${errorMessage}`, params.action, { error: errorMessage });
201
- }
202
- }
203
- /**
204
- * Handle track operation - Manually record a change
205
- */
206
- async handleTrack(params, startTime) {
207
- try {
208
- const currentBranch = await this.getCurrentBranch(params.projectPath);
209
- const timestamp = params.timestamp || new Date().toISOString();
210
- const entry = {
211
- id: `manual-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
212
- timestamp,
213
- author: await this.getProviderUserName() || 'Unknown',
214
- authorEmail: await this.getGitUserEmail() || '',
215
- message: params.message,
216
- filesChanged: params.files ? params.files.map(file => ({
217
- path: file,
218
- status: 'modified',
219
- additions: params.additions || 0,
220
- deletions: params.deletions || 0
221
- })) : [],
222
- additions: params.additions || 0,
223
- deletions: params.deletions || 0,
224
- branch: currentBranch || 'main',
225
- manual: true,
226
- synced: false
227
- };
228
- await this.addHistoryEntry(entry);
229
- return {
230
- success: true,
231
- data: {
232
- entry: entry,
233
- message: 'Change tracked successfully'
234
- },
235
- metadata: {
236
- operation: params.action,
237
- executionTime: Date.now() - startTime,
238
- timestamp: new Date().toISOString()
239
- }
240
- };
241
- }
242
- catch (error) {
243
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
244
- return operation_error_handler_js_1.OperationErrorHandler.createToolError('TRACK_FAILED', `Failed to track change: ${errorMessage}`, params.action, { error: errorMessage });
245
- }
246
- }
247
- /**
248
- * Handle sync operation - Sync local history to remote
249
- */
250
- async handleSync(params, startTime) {
251
- try {
252
- const history = await this.loadHistory();
253
- const unsyncedEntries = history.entries.filter(entry => !entry.synced);
254
- if (unsyncedEntries.length === 0) {
255
- return {
256
- success: true,
257
- data: {
258
- message: 'All entries are already synced',
259
- totalEntries: history.entries.length,
260
- syncedEntries: history.entries.length - unsyncedEntries.length,
261
- unsyncedEntries: 0
262
- },
263
- metadata: {
264
- operation: params.action,
265
- executionTime: Date.now() - startTime,
266
- timestamp: new Date().toISOString()
267
- }
268
- };
269
- }
270
- const syncMethod = params.syncMethod || 'file';
271
- let syncResult = {};
272
- if (syncMethod === 'file') {
273
- syncResult = await this.syncViaFile(params, unsyncedEntries);
274
- }
275
- else if (syncMethod === 'api') {
276
- syncResult = await this.syncViaApi(params, unsyncedEntries);
277
- }
278
- else {
279
- return operation_error_handler_js_1.OperationErrorHandler.createToolError('INVALID_SYNC_METHOD', `Invalid sync method: ${syncMethod}`, params.action, { supportedMethods: ['file', 'api'] }, ['Use "file" to commit history.json or "api" to use provider API']);
280
- }
281
- // Mark entries as synced
282
- const updatedHistory = await this.loadHistory();
283
- updatedHistory.entries.forEach(entry => {
284
- if (!entry.synced && unsyncedEntries.some(u => u.id === entry.id)) {
285
- entry.synced = true;
286
- }
287
- });
288
- await this.saveHistory(updatedHistory);
289
- return {
290
- success: true,
291
- data: {
292
- ...syncResult,
293
- syncedEntries: unsyncedEntries.length,
294
- totalEntries: history.entries.length,
295
- syncMethod
296
- },
297
- metadata: {
298
- operation: params.action,
299
- executionTime: Date.now() - startTime,
300
- timestamp: new Date().toISOString()
301
- }
302
- };
303
- }
304
- catch (error) {
305
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
306
- return operation_error_handler_js_1.OperationErrorHandler.createToolError('SYNC_FAILED', `Failed to sync history: ${errorMessage}`, params.action, { error: errorMessage });
307
- }
308
- }
309
- /**
310
- * Handle export operation - Export history to file
311
- */
312
- async handleExport(params, startTime) {
313
- try {
314
- const history = await this.loadHistory();
315
- const outputPath = params.outputPath || path.join(params.projectPath, 'HISTORY.json');
316
- let exportData;
317
- if (path.extname(outputPath).toLowerCase() === '.md') {
318
- // Export as Markdown
319
- exportData = this.formatHistoryAsMarkdown(history.entries);
320
- }
321
- else {
322
- // Export as JSON
323
- exportData = {
324
- exportedAt: new Date().toISOString(),
325
- totalEntries: history.entries.length,
326
- includeDiffs: params.includeDiffs || false,
327
- entries: params.includeDiffs ? history.entries : history.entries.map(entry => {
328
- const { diff, ...entryWithoutDiff } = entry;
329
- return entryWithoutDiff;
330
- })
331
- };
332
- }
333
- // Write to file
334
- const outputDir = path.dirname(outputPath);
335
- if (!fs.existsSync(outputDir)) {
336
- fs.mkdirSync(outputDir, { recursive: true });
337
- }
338
- if (typeof exportData === 'string') {
339
- fs.writeFileSync(outputPath, exportData, 'utf8');
340
- }
341
- else {
342
- fs.writeFileSync(outputPath, JSON.stringify(exportData, null, 2), 'utf8');
343
- }
344
- return {
345
- success: true,
346
- data: {
347
- exportedPath: outputPath,
348
- format: path.extname(outputPath).toLowerCase() === '.md' ? 'markdown' : 'json',
349
- totalEntries: history.entries.length,
350
- includeDiffs: params.includeDiffs || false
351
- },
352
- metadata: {
353
- operation: params.action,
354
- executionTime: Date.now() - startTime,
355
- timestamp: new Date().toISOString()
356
- }
357
- };
358
- }
359
- catch (error) {
360
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
361
- return operation_error_handler_js_1.OperationErrorHandler.createToolError('EXPORT_FAILED', `Failed to export history: ${errorMessage}`, params.action, { error: errorMessage });
362
- }
363
- }
364
- /**
365
- * Handle auto operation - Enable/disable automatic tracking
366
- */
367
- async handleAuto(params, startTime) {
368
- try {
369
- const config = await this.loadConfig();
370
- const wasEnabled = config.autoTracking;
371
- if (params.enabled !== undefined) {
372
- config.autoTracking = params.enabled;
373
- await this.saveConfig(config);
374
- if (params.enabled && !wasEnabled) {
375
- // Enable auto-tracking - sync current commits
376
- await this.syncRecentCommits();
377
- }
378
- }
379
- return {
380
- success: true,
381
- data: {
382
- autoTrackingEnabled: config.autoTracking,
383
- message: `Auto-tracking ${config.autoTracking ? 'enabled' : 'disabled'}`
384
- },
385
- metadata: {
386
- operation: params.action,
387
- executionTime: Date.now() - startTime,
388
- timestamp: new Date().toISOString()
389
- }
390
- };
391
- }
392
- catch (error) {
393
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
394
- return operation_error_handler_js_1.OperationErrorHandler.createToolError('AUTO_CONFIG_FAILED', `Failed to configure auto-tracking: ${errorMessage}`, params.action, { error: errorMessage });
395
- }
396
- }
397
- /**
398
- * Sync via file commit
399
- */
400
- async syncViaFile(params, entries) {
401
- try {
402
- const historyFile = path.join(params.projectPath, 'HISTORY.json');
403
- // Write history to repository
404
- const historyData = {
405
- lastUpdated: new Date().toISOString(),
406
- entries: entries
407
- };
408
- fs.writeFileSync(historyFile, JSON.stringify(historyData, null, 2), 'utf8');
409
- // Commit the file
410
- const addResult = await this.gitExecutor.executeGitCommand('add', ['HISTORY.json'], params.projectPath);
411
- if (!addResult.success) {
412
- throw new Error(`Failed to add HISTORY.json: ${addResult.stderr}`);
413
- }
414
- const commitResult = await this.gitExecutor.executeGitCommand('commit', ['-m', `Update history: ${entries.length} new entries`], params.projectPath);
415
- if (!commitResult.success && !commitResult.stderr.includes('nothing to commit')) {
416
- throw new Error(`Failed to commit HISTORY.json: ${commitResult.stderr}`);
417
- }
418
- return {
419
- method: 'file',
420
- committed: commitResult.success,
421
- message: 'History synced via file commit'
422
- };
423
- }
424
- catch (error) {
425
- throw new Error(`File sync failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
426
- }
427
- }
428
- /**
429
- * Sync via provider API
430
- */
431
- async syncViaApi(params, entries) {
432
- if (!this.providerHandler) {
433
- throw new Error('Provider handler not configured');
434
- }
435
- try {
436
- const provider = params.provider || 'github';
437
- const repo = params.repo || await this.getRepoName();
438
- // Create a summary entry for the API
439
- const summary = {
440
- period: `${entries[0]?.timestamp} to ${entries[entries.length - 1]?.timestamp}`,
441
- totalEntries: entries.length,
442
- authors: [...new Set(entries.map(e => e.author))],
443
- filesChanged: entries.reduce((sum, e) => sum + e.filesChanged.length, 0),
444
- totalAdditions: entries.reduce((sum, e) => sum + e.additions, 0),
445
- totalDeletions: entries.reduce((sum, e) => sum + e.deletions, 0),
446
- entries: entries.slice(0, 10) // Include first 10 entries in detail
447
- };
448
- const operation = {
449
- provider,
450
- operation: 'create',
451
- parameters: {
452
- repo,
453
- title: `History Update: ${entries.length} changes`,
454
- body: JSON.stringify(summary, null, 2),
455
- type: 'issue' // Create as issue for tracking
456
- },
457
- requiresAuth: true,
458
- isRemoteOperation: true
459
- };
460
- const result = await this.providerHandler.executeOperation(operation);
461
- return {
462
- method: 'api',
463
- provider,
464
- success: result.success,
465
- message: result.success ? 'History synced via API' : 'API sync failed'
466
- };
467
- }
468
- catch (error) {
469
- throw new Error(`API sync failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
470
- }
471
- }
472
- /**
473
- * Format history as Markdown
474
- */
475
- formatHistoryAsMarkdown(entries) {
476
- let markdown = '# Repository History\n\n';
477
- markdown += `Generated on: ${new Date().toISOString()}\n\n`;
478
- markdown += `Total entries: ${entries.length}\n\n`;
479
- for (const entry of entries) {
480
- markdown += `## ${entry.message}\n\n`;
481
- markdown += `- **Date:** ${new Date(entry.timestamp).toLocaleString()}\n`;
482
- markdown += `- **Author:** ${entry.author} <${entry.authorEmail}>\n`;
483
- markdown += `- **Branch:** ${entry.branch}\n`;
484
- markdown += `- **Commit:** ${entry.commitHash || 'Manual entry'}\n`;
485
- markdown += `- **Changes:** +${entry.additions} -${entry.deletions}\n`;
486
- if (entry.filesChanged.length > 0) {
487
- markdown += `- **Files changed:**\n`;
488
- for (const file of entry.filesChanged) {
489
- markdown += ` - ${file.status.toUpperCase()}: ${file.path} (+${file.additions} -${file.deletions})\n`;
490
- }
491
- }
492
- if (entry.tags && entry.tags.length > 0) {
493
- markdown += `- **Tags:** ${entry.tags.join(', ')}\n`;
494
- }
495
- markdown += '\n---\n\n';
496
- }
497
- return markdown;
498
- }
499
- /**
500
- * Load history from file
501
- */
502
- async loadHistory() {
503
- try {
504
- if (fs.existsSync(this.historyPath)) {
505
- const data = fs.readFileSync(this.historyPath, 'utf8');
506
- return JSON.parse(data);
507
- }
508
- }
509
- catch (error) {
510
- console.warn('Failed to load history file:', error);
511
- }
512
- return { entries: [] };
513
- }
514
- /**
515
- * Save history to file
516
- */
517
- async saveHistory(history) {
518
- try {
519
- fs.writeFileSync(this.historyPath, JSON.stringify(history, null, 2), 'utf8');
520
- }
521
- catch (error) {
522
- throw new Error(`Failed to save history: ${error instanceof Error ? error.message : 'Unknown error'}`);
523
- }
524
- }
525
- /**
526
- * Add entry to history
527
- */
528
- async addHistoryEntry(entry) {
529
- const history = await this.loadHistory();
530
- history.entries.push(entry);
531
- await this.saveHistory(history);
532
- }
533
- /**
534
- * Load configuration
535
- */
536
- async loadConfig() {
537
- try {
538
- if (fs.existsSync(this.configPath)) {
539
- const data = fs.readFileSync(this.configPath, 'utf8');
540
- return JSON.parse(data);
541
- }
542
- }
543
- catch (error) {
544
- console.warn('Failed to load config file:', error);
545
- }
546
- return { autoTracking: false };
547
- }
548
- /**
549
- * Save configuration
550
- */
551
- async saveConfig(config) {
552
- try {
553
- fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf8');
554
- }
555
- catch (error) {
556
- throw new Error(`Failed to save config: ${error instanceof Error ? error.message : 'Unknown error'}`);
557
- }
558
- }
559
- /**
560
- * Sync recent commits to history
561
- */
562
- async syncRecentCommits() {
563
- try {
564
- const config = await this.loadConfig();
565
- const lastHash = config.lastCommitHash;
566
- // Get commits since last sync
567
- const logArgs = ['--oneline', '--numstat', '--format=format:%H|%an|%ae|%ad|%s'];
568
- if (lastHash) {
569
- logArgs.push(`${lastHash}..HEAD`);
570
- }
571
- const logResult = await this.gitExecutor.executeGitCommand('log', logArgs);
572
- if (!logResult.success) {
573
- console.warn('Failed to get git log:', logResult.stderr);
574
- return;
575
- }
576
- const lines = logResult.stdout.split('\n').filter(line => line.trim());
577
- let currentEntry = null;
578
- for (const line of lines) {
579
- if (line.includes('|')) {
580
- // Commit header line
581
- if (currentEntry) {
582
- await this.addHistoryEntry(currentEntry);
583
- }
584
- const [hash, gitAuthor, email, date, ...messageParts] = line.split('|');
585
- const message = messageParts.join('|');
586
- currentEntry = {
587
- id: `commit-${hash}`,
588
- timestamp: new Date(date).toISOString(),
589
- commitHash: hash,
590
- author: await this.getProviderUserName() || gitAuthor, // Use provider username, fallback to git author
591
- authorEmail: email,
592
- message,
593
- filesChanged: [],
594
- additions: 0,
595
- deletions: 0,
596
- branch: await this.getCurrentBranch() || 'main',
597
- synced: false
598
- };
599
- }
600
- else if (line.trim() && currentEntry) {
601
- // File change line (from --numstat)
602
- const parts = line.trim().split('\t');
603
- if (parts.length >= 3) {
604
- const additions = parseInt(parts[0]) || 0;
605
- const deletions = parseInt(parts[1]) || 0;
606
- const filePath = parts[2];
607
- currentEntry.filesChanged.push({
608
- path: filePath,
609
- status: additions === 0 && deletions === 0 ? 'modified' : (additions > 0 ? 'added' : 'deleted'),
610
- additions,
611
- deletions
612
- });
613
- currentEntry.additions += additions;
614
- currentEntry.deletions += deletions;
615
- }
616
- }
617
- }
618
- // Add the last entry
619
- if (currentEntry) {
620
- await this.addHistoryEntry(currentEntry);
621
- }
622
- // Update last commit hash
623
- const latestHash = await this.getLatestCommitHash();
624
- if (latestHash) {
625
- config.lastCommitHash = latestHash;
626
- config.lastSyncTimestamp = new Date().toISOString();
627
- await this.saveConfig(config);
628
- }
629
- }
630
- catch (error) {
631
- console.warn('Failed to sync recent commits:', error);
632
- }
633
- }
634
- /**
635
- * Get current branch
636
- */
637
- async getCurrentBranch(projectPath) {
638
- try {
639
- const result = await this.gitExecutor.executeGitCommand('branch', ['--show-current'], projectPath);
640
- return result.success ? result.stdout.trim() : null;
641
- }
642
- catch {
643
- return null;
644
- }
645
- }
646
- /**
647
- * Get provider username (GitHub or Gitea username from env)
648
- */
649
- async getProviderUserName() {
650
- // Try GitHub username first
651
- const githubUser = process.env.GITHUB_USERNAME;
652
- if (githubUser)
653
- return githubUser;
654
- // Try Gitea username
655
- const giteaUser = process.env.GITEA_USERNAME;
656
- if (giteaUser)
657
- return giteaUser;
658
- // Fallback to git config user name
659
- try {
660
- const result = await this.gitExecutor.executeGitCommand('config', ['user.name']);
661
- return result.success ? result.stdout.trim() : null;
662
- }
663
- catch {
664
- return null;
665
- }
666
- }
667
- /**
668
- * Get git user email
669
- */
670
- async getGitUserEmail() {
671
- try {
672
- const result = await this.gitExecutor.executeGitCommand('config', ['user.email']);
673
- return result.success ? result.stdout.trim() : null;
674
- }
675
- catch {
676
- return null;
677
- }
678
- }
679
- /**
680
- * Get latest commit hash
681
- */
682
- async getLatestCommitHash() {
683
- try {
684
- const result = await this.gitExecutor.executeGitCommand('rev-parse', ['HEAD']);
685
- return result.success ? result.stdout.trim() : null;
686
- }
687
- catch {
688
- return null;
689
- }
690
- }
691
- /**
692
- * Get repository name from git config
693
- */
694
- async getRepoName() {
695
- try {
696
- const result = await this.gitExecutor.executeGitCommand('config', ['--get', 'remote.origin.url']);
697
- if (result.success) {
698
- const url = result.stdout.trim();
699
- // Extract repo name from URL (supports GitHub and Gitea formats)
700
- const match = url.match(/\/([^\/]+?)(?:\.git)?$/);
701
- return match ? match[1] : null;
702
- }
703
- }
704
- catch {
705
- // Ignore errors
706
- }
707
- return null;
708
- }
709
- /**
710
- * Ensure history directory exists
711
- */
712
- ensureHistoryDirectory() {
713
- try {
714
- const dir = path.dirname(this.historyPath);
715
- if (!fs.existsSync(dir)) {
716
- fs.mkdirSync(dir, { recursive: true });
717
- }
718
- }
719
- catch (error) {
720
- console.warn('Failed to create history directory:', error);
721
- }
722
- }
723
- /**
724
- * Get tool schema for MCP registration
725
- */
726
- static getToolSchema() {
727
- return {
728
- name: 'git-history',
729
- description: 'Comprehensive change tracking tool that records all repository modifications with detailed timestamps, storing history locally in JSON and syncing to remote providers.',
730
- inputSchema: {
731
- type: 'object',
732
- properties: {
733
- action: {
734
- type: 'string',
735
- enum: ['log', 'track', 'sync', 'export', 'auto'],
736
- description: 'The git-history operation to perform'
737
- },
738
- projectPath: {
739
- type: 'string',
740
- description: 'Absolute path to the project directory'
741
- },
742
- limit: {
743
- type: 'number',
744
- description: 'Number of entries to show (default: 50)',
745
- minimum: 1,
746
- maximum: 1000
747
- },
748
- since: {
749
- type: 'string',
750
- description: 'Start date filter (ISO 8601 format)'
751
- },
752
- until: {
753
- type: 'string',
754
- description: 'End date filter (ISO 8601 format)'
755
- },
756
- author: {
757
- type: 'string',
758
- description: 'Filter by author name or email'
759
- },
760
- filePath: {
761
- type: 'string',
762
- description: 'Filter by file path'
763
- },
764
- branch: {
765
- type: 'string',
766
- description: 'Filter by branch name'
767
- },
768
- format: {
769
- type: 'string',
770
- enum: ['json', 'markdown'],
771
- description: 'Output format for log operation'
772
- },
773
- message: {
774
- type: 'string',
775
- description: 'Change description (required for track operation)'
776
- },
777
- timestamp: {
778
- type: 'string',
779
- description: 'Custom timestamp for track operation (ISO 8601 format)'
780
- },
781
- files: {
782
- type: 'array',
783
- items: { type: 'string' },
784
- description: 'Files affected by the change (for track operation)'
785
- },
786
- additions: {
787
- type: 'number',
788
- description: 'Lines added (for track operation)',
789
- minimum: 0
790
- },
791
- deletions: {
792
- type: 'number',
793
- description: 'Lines deleted (for track operation)',
794
- minimum: 0
795
- },
796
- syncMethod: {
797
- type: 'string',
798
- enum: ['file', 'api'],
799
- description: 'Sync method: file (commit to repo) or api (use provider API)'
800
- },
801
- repo: {
802
- type: 'string',
803
- description: 'Repository name for remote sync'
804
- },
805
- outputPath: {
806
- type: 'string',
807
- description: 'Export file path (absolute path required)'
808
- },
809
- includeDiffs: {
810
- type: 'boolean',
811
- description: 'Include full diffs in export (default: false)'
812
- },
813
- enabled: {
814
- type: 'boolean',
815
- description: 'Enable/disable auto-tracking (for auto operation)'
816
- }
817
- },
818
- required: ['action', 'projectPath']
819
- }
820
- };
821
- }
822
- }
823
- exports.GitHistoryTool = GitHistoryTool;
824
- //# sourceMappingURL=git-history.js.map