@andrebuzeli/git-mcp 3.4.0 → 4.0.3

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 (141) hide show
  1. package/EXEMPLOS.md +861 -0
  2. package/INSTRUCOES.md +444 -0
  3. package/README.md +63 -283
  4. package/dist/providers/base-provider.d.ts.map +1 -1
  5. package/dist/providers/base-provider.js +3 -26
  6. package/dist/providers/base-provider.js.map +1 -1
  7. package/dist/providers/gitea-provider.d.ts +0 -2
  8. package/dist/providers/gitea-provider.d.ts.map +1 -1
  9. package/dist/providers/gitea-provider.js +0 -62
  10. package/dist/providers/gitea-provider.js.map +1 -1
  11. package/dist/providers/github-provider.d.ts +0 -2
  12. package/dist/providers/github-provider.d.ts.map +1 -1
  13. package/dist/providers/github-provider.js +48 -105
  14. package/dist/providers/github-provider.js.map +1 -1
  15. package/dist/server.d.ts +0 -27
  16. package/dist/server.d.ts.map +1 -1
  17. package/dist/server.js +130 -1215
  18. package/dist/server.js.map +1 -1
  19. package/dist/tools/{git-commits.d.ts → git-analytics.d.ts} +4 -10
  20. package/dist/tools/git-analytics.d.ts.map +1 -0
  21. package/dist/tools/git-analytics.js +18 -0
  22. package/dist/tools/git-analytics.js.map +1 -0
  23. package/dist/tools/git-archive.d.ts +3 -0
  24. package/dist/tools/git-archive.d.ts.map +1 -1
  25. package/dist/tools/git-archive.js +2 -2
  26. package/dist/tools/git-archive.js.map +1 -1
  27. package/dist/tools/git-backup.d.ts +216 -0
  28. package/dist/tools/git-backup.d.ts.map +1 -0
  29. package/dist/tools/git-backup.js +813 -0
  30. package/dist/tools/git-backup.js.map +1 -0
  31. package/dist/tools/git-branches.d.ts +159 -8
  32. package/dist/tools/git-branches.d.ts.map +1 -1
  33. package/dist/tools/git-branches.js +554 -2
  34. package/dist/tools/git-branches.js.map +1 -1
  35. package/dist/tools/git-config.d.ts +3 -0
  36. package/dist/tools/git-config.d.ts.map +1 -1
  37. package/dist/tools/git-config.js +2 -2
  38. package/dist/tools/git-config.js.map +1 -1
  39. package/dist/tools/git-files.d.ts +130 -8
  40. package/dist/tools/git-files.d.ts.map +1 -1
  41. package/dist/tools/git-files.js +426 -2
  42. package/dist/tools/git-files.js.map +1 -1
  43. package/dist/tools/git-issues.d.ts +137 -471
  44. package/dist/tools/git-issues.d.ts.map +1 -1
  45. package/dist/tools/git-issues.js +605 -613
  46. package/dist/tools/git-issues.js.map +1 -1
  47. package/dist/tools/git-monitor.d.ts +161 -0
  48. package/dist/tools/git-monitor.d.ts.map +1 -0
  49. package/dist/tools/git-monitor.js +746 -0
  50. package/dist/tools/git-monitor.js.map +1 -0
  51. package/dist/tools/git-packages.d.ts +5 -2
  52. package/dist/tools/git-packages.d.ts.map +1 -1
  53. package/dist/tools/git-packages.js +3 -3
  54. package/dist/tools/git-packages.js.map +1 -1
  55. package/dist/tools/git-pulls.d.ts +38 -646
  56. package/dist/tools/git-pulls.d.ts.map +1 -1
  57. package/dist/tools/git-pulls.js +64 -716
  58. package/dist/tools/git-pulls.js.map +1 -1
  59. package/dist/tools/git-release.d.ts +187 -0
  60. package/dist/tools/git-release.d.ts.map +1 -0
  61. package/dist/tools/git-release.js +619 -0
  62. package/dist/tools/git-release.js.map +1 -0
  63. package/dist/tools/git-remote.d.ts +112 -77
  64. package/dist/tools/git-remote.d.ts.map +1 -1
  65. package/dist/tools/git-remote.js +481 -183
  66. package/dist/tools/git-remote.js.map +1 -1
  67. package/dist/tools/git-repos.d.ts +19 -0
  68. package/dist/tools/git-repos.d.ts.map +1 -0
  69. package/dist/tools/git-repos.js +18 -0
  70. package/dist/tools/git-repos.js.map +1 -0
  71. package/dist/tools/git-reset.d.ts +121 -74
  72. package/dist/tools/git-reset.d.ts.map +1 -1
  73. package/dist/tools/git-reset.js +540 -159
  74. package/dist/tools/git-reset.js.map +1 -1
  75. package/dist/tools/git-stash.d.ts +119 -78
  76. package/dist/tools/git-stash.d.ts.map +1 -1
  77. package/dist/tools/git-stash.js +560 -209
  78. package/dist/tools/git-stash.js.map +1 -1
  79. package/dist/tools/git-sync.d.ts +3 -163
  80. package/dist/tools/git-sync.d.ts.map +1 -1
  81. package/dist/tools/git-sync.js +9 -326
  82. package/dist/tools/git-sync.js.map +1 -1
  83. package/dist/tools/git-tags.d.ts +105 -331
  84. package/dist/tools/git-tags.d.ts.map +1 -1
  85. package/dist/tools/git-tags.js +545 -416
  86. package/dist/tools/git-tags.js.map +1 -1
  87. package/dist/tools/git-workflow.d.ts +127 -0
  88. package/dist/tools/git-workflow.d.ts.map +1 -0
  89. package/dist/tools/git-workflow.js +359 -0
  90. package/dist/tools/git-workflow.js.map +1 -0
  91. package/dist/utils/auto-detection.d.ts +113 -0
  92. package/dist/utils/auto-detection.d.ts.map +1 -0
  93. package/dist/utils/auto-detection.js +235 -0
  94. package/dist/utils/auto-detection.js.map +1 -0
  95. package/dist/utils/error-handler.d.ts +107 -0
  96. package/dist/utils/error-handler.d.ts.map +1 -0
  97. package/dist/utils/error-handler.js +331 -0
  98. package/dist/utils/error-handler.js.map +1 -0
  99. package/dist/utils/git-operations.d.ts.map +1 -1
  100. package/dist/utils/git-operations.js +6 -51
  101. package/dist/utils/git-operations.js.map +1 -1
  102. package/dist/utils/user-detection.d.ts +1 -13
  103. package/dist/utils/user-detection.d.ts.map +1 -1
  104. package/dist/utils/user-detection.js +1 -26
  105. package/dist/utils/user-detection.js.map +1 -1
  106. package/package.json +62 -60
  107. package/dist/client.d.ts +0 -307
  108. package/dist/client.d.ts.map +0 -1
  109. package/dist/client.js +0 -299
  110. package/dist/client.js.map +0 -1
  111. package/dist/tools/git-branch-protection.d.ts +0 -97
  112. package/dist/tools/git-branch-protection.d.ts.map +0 -1
  113. package/dist/tools/git-branch-protection.js +0 -182
  114. package/dist/tools/git-branch-protection.js.map +0 -1
  115. package/dist/tools/git-commits.d.ts.map +0 -1
  116. package/dist/tools/git-commits.js +0 -5
  117. package/dist/tools/git-commits.js.map +0 -1
  118. package/dist/tools/git-initialize.d.ts +0 -208
  119. package/dist/tools/git-initialize.d.ts.map +0 -1
  120. package/dist/tools/git-initialize.js +0 -470
  121. package/dist/tools/git-initialize.js.map +0 -1
  122. package/dist/tools/git-projects.d.ts +0 -112
  123. package/dist/tools/git-projects.d.ts.map +0 -1
  124. package/dist/tools/git-projects.js +0 -319
  125. package/dist/tools/git-projects.js.map +0 -1
  126. package/dist/tools/git-releases.d.ts +0 -486
  127. package/dist/tools/git-releases.d.ts.map +0 -1
  128. package/dist/tools/git-releases.js +0 -561
  129. package/dist/tools/git-releases.js.map +0 -1
  130. package/dist/tools/git-repositories.d.ts +0 -469
  131. package/dist/tools/git-repositories.d.ts.map +0 -1
  132. package/dist/tools/git-repositories.js +0 -637
  133. package/dist/tools/git-repositories.js.map +0 -1
  134. package/dist/tools/git-revert.d.ts +0 -147
  135. package/dist/tools/git-revert.d.ts.map +0 -1
  136. package/dist/tools/git-revert.js +0 -199
  137. package/dist/tools/git-revert.js.map +0 -1
  138. package/dist/tools/git-update-project.d.ts +0 -309
  139. package/dist/tools/git-update-project.d.ts.map +0 -1
  140. package/dist/tools/git-update-project.js +0 -878
  141. package/dist/tools/git-update-project.js.map +0 -1
@@ -2,263 +2,561 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.gitRemoteTool = void 0;
4
4
  const zod_1 = require("zod");
5
- const terminal_controller_js_1 = require("../utils/terminal-controller.js");
5
+ const auto_detection_js_1 = require("../utils/auto-detection.js");
6
+ const error_handler_js_1 = require("../utils/error-handler.js");
6
7
  const git_operations_js_1 = require("../utils/git-operations.js");
7
8
  /**
8
9
  * Tool: git-remote
9
10
  *
10
- * DESCRIÇÃO:
11
- * Gerenciamento de remotes Git (GitHub + Gitea) com múltiplas ações
11
+ * GERENCIAMENTO DE REMOTOS UNIFICADO
12
+ * Remotes com auto-configuração, multi-provider e validação inteligente
12
13
  *
13
- * FUNCIONALIDADES:
14
- * - Adicionar remote
15
- * - Remover remote
16
- * - Renomear remote
17
- * - Mostrar remotes
18
- * - Definir URL do remote
19
- * - Prune remotes
20
- *
21
- * USO:
22
- * - Para configurar repositórios remotos
23
- * - Para gerenciar múltiplos remotes
24
- * - Para sincronizar com diferentes servidores
25
- * - Para configurar upstream
26
- *
27
- * RECOMENDAÇÕES:
28
- * - Use 'origin' como remote principal
29
- * - Configure upstream para branches
30
- * - Mantenha URLs atualizadas
14
+ * DESIGNED FOR: Programador individual autônomo
15
+ * PHILOSOPHY: Remotes transparentes e auto-gerenciados
31
16
  */
32
- const GitRemoteInputSchema = zod_1.z.object({
33
- action: zod_1.z.enum(['add', 'remove', 'rename', 'show', 'set-url', 'prune']),
34
- // owner: obtido automaticamente do provider,
35
- // repo: extraído automaticamente do projectPath
36
- provider: zod_1.z.enum(['gitea', 'github']).describe('Provider to use (gitea or github)'),
37
- projectPath: zod_1.z.string().describe('Local project path for git operations'),
38
- // Para add/set-url
39
- remote_name: zod_1.z.string().optional(),
40
- remote_url: zod_1.z.string().optional(),
41
- // Para remove/rename/show
42
- remote: zod_1.z.string().optional(),
43
- // Para rename
44
- new_name: zod_1.z.string().optional(),
45
- // Para prune
46
- remote_to_prune: zod_1.z.string().optional(),
47
- });
48
- const GitRemoteResultSchema = zod_1.z.object({
49
- success: zod_1.z.boolean(),
50
- action: zod_1.z.string(),
51
- message: zod_1.z.string(),
52
- data: zod_1.z.any().optional(),
53
- error: zod_1.z.string().optional()
54
- });
55
- exports.gitRemoteTool = {
56
- name: 'git-remote',
57
- description: 'tool: Gerencia repositórios remotos Git para sincronização\n──────────────\naction add: adiciona novo remote\naction add requires: remote_name, remote_url, provider\n───────────────\naction remove: remove remote\naction remove requires: remote, provider\n───────────────\naction rename: renomeia remote\naction rename requires: remote, new_name, provider\n───────────────\naction show: mostra informações do remote\naction show requires: remote, provider\n───────────────\naction set-url: atualiza URL do remote\naction set-url requires: remote, remote_url, provider\n───────────────\naction prune: remove referências obsoletas\naction prune requires: remote_to_prune, provider',
58
- inputSchema: {
59
- type: 'object',
60
- properties: {
61
- action: {
62
- type: 'string',
63
- enum: ['add', 'remove', 'rename', 'show', 'set-url', 'prune'],
64
- description: 'Action to perform on remotes'
65
- },
66
- owner: { type: 'string', description: 'Repository owner' },
67
- repo: { type: 'string', description: 'Repository name' },
68
- provider: { type: 'string', enum: ['gitea', 'github'], description: 'Provider to use (gitea or github)' },
69
- projectPath: { type: 'string', description: 'Local project path for git operations' },
70
- remote_name: { type: 'string', description: 'Remote name' },
71
- remote_url: { type: 'string', description: 'Remote URL' },
72
- remote: { type: 'string', description: 'Remote to operate on' },
73
- new_name: { type: 'string', description: 'New remote name' },
74
- remote_to_prune: { type: 'string', description: 'Remote to prune' }
75
- },
76
- required: ['action', 'repo', 'provider', 'projectPath']
77
- },
78
- async handler(input) {
17
+ const GitRemoteInputSchema = zod_1.z.discriminatedUnion('action', [
18
+ // ADD REMOTE - Adição inteligente
19
+ zod_1.z.object({
20
+ action: zod_1.z.literal('add'),
21
+ projectPath: zod_1.z.string(),
22
+ name: zod_1.z.string(),
23
+ url: zod_1.z.string(),
24
+ provider: zod_1.z.enum(['gitea', 'github']).optional() // Auto-detect se não fornecido
25
+ }),
26
+ // REMOVE REMOTE - Remoção segura
27
+ zod_1.z.object({
28
+ action: zod_1.z.literal('remove'),
29
+ projectPath: zod_1.z.string(),
30
+ name: zod_1.z.string(),
31
+ force: zod_1.z.boolean().default(false)
32
+ }),
33
+ // RENAME REMOTE - Renomeação
34
+ zod_1.z.object({
35
+ action: zod_1.z.literal('rename'),
36
+ projectPath: zod_1.z.string(),
37
+ oldName: zod_1.z.string(),
38
+ newName: zod_1.z.string()
39
+ }),
40
+ // SHOW REMOTE - Informações detalhadas
41
+ zod_1.z.object({
42
+ action: zod_1.z.literal('show'),
43
+ projectPath: zod_1.z.string(),
44
+ name: zod_1.z.string().optional(), // Todos se não especificado
45
+ detailed: zod_1.z.boolean().default(false)
46
+ }),
47
+ // SET-URL REMOTE - Atualização de URL
48
+ zod_1.z.object({
49
+ action: zod_1.z.literal('set-url'),
50
+ projectPath: zod_1.z.string(),
51
+ name: zod_1.z.string(),
52
+ url: zod_1.z.string(),
53
+ push: zod_1.z.boolean().default(false) // Para push URL diferente
54
+ }),
55
+ // PRUNE REMOTE - Limpeza de referências
56
+ zod_1.z.object({
57
+ action: zod_1.z.literal('prune'),
58
+ projectPath: zod_1.z.string(),
59
+ name: zod_1.z.string(),
60
+ dryRun: zod_1.z.boolean().default(false)
61
+ })
62
+ ]);
63
+ /**
64
+ * Smart Remote Manager
65
+ * Gerencia operações de remotos com inteligência
66
+ */
67
+ class SmartRemoteManager {
68
+ static async getAllRemotes(projectPath) {
69
+ const gitOps = new git_operations_js_1.GitOperations(projectPath);
79
70
  try {
80
- const validatedInput = GitRemoteInputSchema.parse(input);
81
- switch (validatedInput.action) {
82
- case 'add':
83
- return await this.add(validatedInput);
84
- case 'remove':
85
- return await this.remove(validatedInput);
86
- case 'rename':
87
- return await this.rename(validatedInput);
88
- case 'show':
89
- return await this.show(validatedInput);
90
- case 'set-url':
91
- return await this.setUrl(validatedInput);
92
- case 'prune':
93
- return await this.prune(validatedInput);
94
- default:
95
- throw new Error(`Ação não suportada: ${validatedInput.action}`);
71
+ const result = await gitOps.runCommand('git', ['remote', '-v']);
72
+ if (!result.success) {
73
+ return [];
96
74
  }
75
+ const lines = result.output.trim().split('\n');
76
+ const remotes = {};
77
+ lines.forEach(line => {
78
+ const match = line.match(/^(\S+)\s+(\S+)\s+\((fetch|push)\)$/);
79
+ if (match) {
80
+ const [_, name, url, type] = match;
81
+ if (!remotes[name]) {
82
+ remotes[name] = { name, urls: {} };
83
+ }
84
+ remotes[name].urls[type] = url;
85
+ }
86
+ });
87
+ return Object.values(remotes);
97
88
  }
98
89
  catch (error) {
90
+ return [];
91
+ }
92
+ }
93
+ static async getRemoteInfo(projectPath, name) {
94
+ const gitOps = new git_operations_js_1.GitOperations(projectPath);
95
+ try {
96
+ // Get basic info
97
+ const showResult = await gitOps.runCommand('git', ['remote', 'show', name]);
98
+ if (!showResult.success) {
99
+ return { name, exists: false };
100
+ }
101
+ // Get URLs
102
+ const urlResult = await gitOps.runCommand('git', ['remote', 'get-url', name]);
103
+ const pushUrlResult = await gitOps.runCommand('git', ['remote', 'get-url', '--push', name]);
104
+ // Detect provider
105
+ const fetchUrl = urlResult.success ? urlResult.output.trim() : '';
106
+ const provider = this.detectProvider(fetchUrl);
99
107
  return {
100
- success: false,
101
- action: input.action,
102
- message: 'Erro na operação de remote',
103
- error: error instanceof Error ? error.message : String(error)
108
+ name,
109
+ exists: true,
110
+ fetchUrl,
111
+ pushUrl: pushUrlResult.success ? pushUrlResult.output.trim() : fetchUrl,
112
+ provider,
113
+ info: showResult.output
104
114
  };
105
115
  }
106
- },
107
- async add(params) {
116
+ catch (error) {
117
+ return { name, exists: false, error: error instanceof Error ? error.message : String(error) };
118
+ }
119
+ }
120
+ static detectProvider(url) {
121
+ if (!url)
122
+ return null;
123
+ if (url.includes('github.com'))
124
+ return 'github';
125
+ if (url.includes('gitea') || url.includes('codeberg.org'))
126
+ return 'gitea';
127
+ // Try to detect from URL pattern
128
+ const patterns = {
129
+ github: /(?:github\.com)/i,
130
+ gitea: /(?:gitea\.|codeberg\.org)/i
131
+ };
132
+ for (const [provider, pattern] of Object.entries(patterns)) {
133
+ if (pattern.test(url)) {
134
+ return provider;
135
+ }
136
+ }
137
+ return null;
138
+ }
139
+ static generateRemoteName(provider, detection) {
140
+ // Generate intelligent remote names
141
+ const baseName = provider === 'gitea' ? 'gitea' : 'github';
142
+ // Check if base name is available
143
+ // For now, just return the base name - could be enhanced to check availability
144
+ return baseName;
145
+ }
146
+ static validateRemoteUrl(url) {
147
+ try {
148
+ new URL(url);
149
+ return { valid: true };
150
+ }
151
+ catch (e) {
152
+ return { valid: false, error: 'Invalid URL format' };
153
+ }
154
+ }
155
+ }
156
+ /**
157
+ * Classe principal para executar operações Git remote
158
+ */
159
+ class GitRemoteExecutor {
160
+ errorHandler = new error_handler_js_1.UniversalErrorHandler();
161
+ /**
162
+ * Executa operação add
163
+ */
164
+ async executeAdd(detection, input) {
108
165
  try {
109
- if (!params.remote_name || !params.remote_url) {
110
- throw new Error('remote_name e remote_url são obrigatórios para add');
166
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
167
+ // Validate URL
168
+ const urlValidation = SmartRemoteManager.validateRemoteUrl(input.url);
169
+ if (!urlValidation.valid) {
170
+ throw new Error(`Invalid remote URL: ${urlValidation.error}`);
111
171
  }
112
- const gitCommand = `remote add ${params.remote_name} ${params.remote_url}`;
113
- const result = await (0, terminal_controller_js_1.runGitCommand)(gitCommand, params.projectPath, 'Adicionando remote');
114
- if (result.exitCode !== 0) {
115
- throw new Error(`Falha ao adicionar remote: ${result.output}`);
172
+ // Detect provider if not specified
173
+ let provider = input.provider;
174
+ if (!provider) {
175
+ provider = SmartRemoteManager.detectProvider(input.url) || 'unknown';
116
176
  }
117
- return {
177
+ // Add remote
178
+ const addResult = await gitOps.runCommand('git', ['remote', 'add', input.name, input.url]);
179
+ if (!addResult.success) {
180
+ throw new Error(`Failed to add remote: ${addResult.error}`);
181
+ }
182
+ // Verify remote was added
183
+ const verifyResult = await SmartRemoteManager.getRemoteInfo(detection.projectPath, input.name);
184
+ return (0, auto_detection_js_1.createUniversalResponse)({
118
185
  success: true,
119
186
  action: 'add',
120
- message: `Remote ${params.remote_name} adicionado com sucesso`,
187
+ message: `Remote '${input.name}' added successfully`,
121
188
  data: {
122
- remote_name: params.remote_name,
123
- remote_url: params.remote_url,
124
- output: result.output
189
+ remote: input.name,
190
+ url: input.url,
191
+ provider: provider,
192
+ verified: verifyResult.exists
193
+ },
194
+ autoDetected: {
195
+ repo: detection.repoName,
196
+ owner: detection.owner,
197
+ providers: detection.providers
125
198
  }
126
- };
199
+ });
127
200
  }
128
201
  catch (error) {
129
- throw new Error(`Falha ao adicionar remote: ${error instanceof Error ? error.message : String(error)}`);
202
+ return this.errorHandler.toUniversalResponse();
130
203
  }
131
- },
132
- async remove(params) {
204
+ }
205
+ /**
206
+ * Executa operação remove
207
+ */
208
+ async executeRemove(detection, input) {
133
209
  try {
134
- if (!params.remote) {
135
- throw new Error('remote é obrigatório para remove');
210
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
211
+ // Check if remote exists
212
+ const remoteInfo = await SmartRemoteManager.getRemoteInfo(detection.projectPath, input.name);
213
+ if (!remoteInfo.exists && !input.force) {
214
+ throw new Error(`Remote '${input.name}' does not exist`);
136
215
  }
137
- const gitCommand = `remote remove ${params.remote}`;
138
- const result = await (0, terminal_controller_js_1.runGitCommand)(gitCommand, params.projectPath, 'Removendo remote');
139
- if (result.exitCode !== 0) {
140
- throw new Error(`Falha ao remover remote: ${result.output}`);
216
+ // Remove remote
217
+ const removeResult = await gitOps.runCommand('git', ['remote', 'remove', input.name]);
218
+ if (!removeResult.success && !input.force) {
219
+ throw new Error(`Failed to remove remote: ${removeResult.error}`);
141
220
  }
142
- return {
221
+ return (0, auto_detection_js_1.createUniversalResponse)({
143
222
  success: true,
144
223
  action: 'remove',
145
- message: `Remote ${params.remote} removido com sucesso`,
224
+ message: `Remote '${input.name}' removed successfully`,
146
225
  data: {
147
- remote: params.remote,
148
- output: result.output
226
+ remote: input.name,
227
+ force: input.force,
228
+ existed: remoteInfo.exists
229
+ },
230
+ autoDetected: {
231
+ repo: detection.repoName,
232
+ owner: detection.owner,
233
+ providers: detection.providers
149
234
  }
150
- };
235
+ });
151
236
  }
152
237
  catch (error) {
153
- throw new Error(`Falha ao remover remote: ${error instanceof Error ? error.message : String(error)}`);
238
+ return this.errorHandler.toUniversalResponse();
154
239
  }
155
- },
156
- async rename(params) {
240
+ }
241
+ /**
242
+ * Executa operação rename
243
+ */
244
+ async executeRename(detection, input) {
157
245
  try {
158
- if (!params.remote || !params.new_name) {
159
- throw new Error('remote e new_name são obrigatórios para rename');
246
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
247
+ // Check if old remote exists
248
+ const oldRemoteInfo = await SmartRemoteManager.getRemoteInfo(detection.projectPath, input.oldName);
249
+ if (!oldRemoteInfo.exists) {
250
+ throw new Error(`Remote '${input.oldName}' does not exist`);
160
251
  }
161
- const gitCommand = `remote rename ${params.remote} ${params.new_name}`;
162
- const result = await (0, terminal_controller_js_1.runGitCommand)(gitCommand, params.projectPath, 'Renomeando remote');
163
- if (result.exitCode !== 0) {
164
- throw new Error(`Falha ao renomear remote: ${result.output}`);
252
+ // Check if new name already exists
253
+ const newRemoteInfo = await SmartRemoteManager.getRemoteInfo(detection.projectPath, input.newName);
254
+ if (newRemoteInfo.exists) {
255
+ throw new Error(`Remote '${input.newName}' already exists`);
165
256
  }
166
- return {
257
+ // Rename remote
258
+ const renameResult = await gitOps.runCommand('git', ['remote', 'rename', input.oldName, input.newName]);
259
+ if (!renameResult.success) {
260
+ throw new Error(`Failed to rename remote: ${renameResult.error}`);
261
+ }
262
+ return (0, auto_detection_js_1.createUniversalResponse)({
167
263
  success: true,
168
264
  action: 'rename',
169
- message: `Remote ${params.remote} renomeado para ${params.new_name} com sucesso`,
265
+ message: `Remote renamed from '${input.oldName}' to '${input.newName}'`,
170
266
  data: {
171
- old_name: params.remote,
172
- new_name: params.new_name,
173
- output: result.output
267
+ oldName: input.oldName,
268
+ newName: input.newName,
269
+ url: oldRemoteInfo.fetchUrl
270
+ },
271
+ autoDetected: {
272
+ repo: detection.repoName,
273
+ owner: detection.owner,
274
+ providers: detection.providers
174
275
  }
175
- };
276
+ });
176
277
  }
177
278
  catch (error) {
178
- throw new Error(`Falha ao renomear remote: ${error instanceof Error ? error.message : String(error)}`);
279
+ return this.errorHandler.toUniversalResponse();
179
280
  }
180
- },
181
- async show(params) {
281
+ }
282
+ /**
283
+ * Executa operação show
284
+ */
285
+ async executeShow(detection, input) {
182
286
  try {
183
- const gitOps = new git_operations_js_1.GitOperations(params.projectPath);
184
- if (!params.remote) {
185
- // Listar todos os remotes
186
- const result = await gitOps.remote('-v');
187
- const remotes = result.output ? result.output.split('\n')
188
- .filter(line => line.trim())
189
- .map(line => {
190
- const parts = line.split('\t');
191
- return { name: parts[0], url: parts[1] };
192
- }) : [];
193
- return {
287
+ if (input.name) {
288
+ // Show specific remote
289
+ const remoteInfo = await SmartRemoteManager.getRemoteInfo(detection.projectPath, input.name);
290
+ if (!remoteInfo.exists) {
291
+ return (0, auto_detection_js_1.createUniversalResponse)({
292
+ success: false,
293
+ action: 'show',
294
+ message: `Remote '${input.name}' not found`,
295
+ error: {
296
+ code: 'REMOTE_NOT_FOUND',
297
+ message: `Remote '${input.name}' does not exist`,
298
+ cause: 'Remote not configured',
299
+ suggestion: 'Add the remote first using the add action'
300
+ },
301
+ autoDetected: {
302
+ repo: detection.repoName,
303
+ owner: detection.owner,
304
+ providers: detection.providers
305
+ }
306
+ });
307
+ }
308
+ return (0, auto_detection_js_1.createUniversalResponse)({
194
309
  success: true,
195
310
  action: 'show',
196
- message: 'Remotes listados com sucesso',
311
+ message: `Remote '${input.name}' information`,
197
312
  data: {
198
- remotes,
199
- output: result.output
313
+ remote: remoteInfo,
314
+ detailed: input.detailed
315
+ },
316
+ autoDetected: {
317
+ repo: detection.repoName,
318
+ owner: detection.owner,
319
+ providers: detection.providers
200
320
  }
201
- };
321
+ });
202
322
  }
203
323
  else {
204
- // Mostrar remote específico
205
- const result = await gitOps.remote('show', params.remote);
206
- if (!result.success) {
207
- throw new Error(`Falha ao mostrar remote: ${result.error || result.output}`);
208
- }
209
- return {
324
+ // Show all remotes
325
+ const remotes = await SmartRemoteManager.getAllRemotes(detection.projectPath);
326
+ return (0, auto_detection_js_1.createUniversalResponse)({
210
327
  success: true,
211
328
  action: 'show',
212
- message: `Remote ${params.remote} mostrado com sucesso`,
329
+ message: `Found ${remotes.length} remotes`,
213
330
  data: {
214
- remote: params.remote,
215
- output: result.output
331
+ remotes: remotes,
332
+ count: remotes.length,
333
+ detailed: input.detailed
334
+ },
335
+ autoDetected: {
336
+ repo: detection.repoName,
337
+ owner: detection.owner,
338
+ providers: detection.providers
216
339
  }
217
- };
340
+ });
218
341
  }
219
342
  }
220
343
  catch (error) {
221
- throw new Error(`Falha ao mostrar remote: ${error instanceof Error ? error.message : String(error)}`);
344
+ return this.errorHandler.toUniversalResponse();
222
345
  }
223
- },
224
- async setUrl(params) {
346
+ }
347
+ /**
348
+ * Executa operação set-url
349
+ */
350
+ async executeSetUrl(detection, input) {
225
351
  try {
226
- const gitOps = new git_operations_js_1.GitOperations(params.projectPath);
227
- const result = await gitOps.remote('set-url', params.remote, params.remote_url);
228
- if (!result.success) {
229
- throw new Error(`Falha ao definir URL do remote: ${result.error || result.output}`);
352
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
353
+ // Validate URL
354
+ const urlValidation = SmartRemoteManager.validateRemoteUrl(input.url);
355
+ if (!urlValidation.valid) {
356
+ throw new Error(`Invalid remote URL: ${urlValidation.error}`);
230
357
  }
231
- return {
358
+ // Check if remote exists
359
+ const remoteInfo = await SmartRemoteManager.getRemoteInfo(detection.projectPath, input.name);
360
+ if (!remoteInfo.exists) {
361
+ throw new Error(`Remote '${input.name}' does not exist`);
362
+ }
363
+ // Set URL
364
+ const args = input.push ? ['remote', 'set-url', '--push', input.name, input.url] : ['remote', 'set-url', input.name, input.url];
365
+ const setResult = await gitOps.runCommand('git', args);
366
+ if (!setResult.success) {
367
+ throw new Error(`Failed to set remote URL: ${setResult.error}`);
368
+ }
369
+ return (0, auto_detection_js_1.createUniversalResponse)({
232
370
  success: true,
233
371
  action: 'set-url',
234
- message: `URL do remote ${params.remote} definida com sucesso`,
372
+ message: `Remote '${input.name}' URL updated successfully`,
235
373
  data: {
236
- remote: params.remote,
237
- remote_url: params.remote_url,
238
- output: result.output
374
+ remote: input.name,
375
+ url: input.url,
376
+ push: input.push,
377
+ previousUrl: input.push ? remoteInfo.pushUrl : remoteInfo.fetchUrl
378
+ },
379
+ autoDetected: {
380
+ repo: detection.repoName,
381
+ owner: detection.owner,
382
+ providers: detection.providers
239
383
  }
240
- };
384
+ });
241
385
  }
242
386
  catch (error) {
243
- throw new Error(`Falha ao definir URL do remote: ${error instanceof Error ? error.message : String(error)}`);
387
+ return this.errorHandler.toUniversalResponse();
244
388
  }
245
- },
246
- async prune(params) {
389
+ }
390
+ /**
391
+ * Executa operação prune
392
+ */
393
+ async executePrune(detection, input) {
247
394
  try {
248
- const gitOps = new git_operations_js_1.GitOperations(params.projectPath);
249
- const result = await gitOps.remote('prune', params.remote_to_prune);
250
- return {
395
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
396
+ // Check if remote exists
397
+ const remoteInfo = await SmartRemoteManager.getRemoteInfo(detection.projectPath, input.name);
398
+ if (!remoteInfo.exists) {
399
+ throw new Error(`Remote '${input.name}' does not exist`);
400
+ }
401
+ // Dry run first
402
+ const dryRunResult = await gitOps.runCommand('git', ['remote', 'prune', '--dry-run', input.name]);
403
+ if (input.dryRun) {
404
+ return (0, auto_detection_js_1.createUniversalResponse)({
405
+ success: true,
406
+ action: 'prune',
407
+ message: `Prune dry-run for remote '${input.name}'`,
408
+ data: {
409
+ remote: input.name,
410
+ dryRun: true,
411
+ wouldRemove: dryRunResult.success ? dryRunResult.output.trim().split('\n').filter(line => line.trim()) : []
412
+ },
413
+ autoDetected: {
414
+ repo: detection.repoName,
415
+ owner: detection.owner,
416
+ providers: detection.providers
417
+ }
418
+ });
419
+ }
420
+ // Actual prune
421
+ const pruneResult = await gitOps.runCommand('git', ['remote', 'prune', input.name]);
422
+ if (!pruneResult.success) {
423
+ throw new Error(`Failed to prune remote: ${pruneResult.error}`);
424
+ }
425
+ return (0, auto_detection_js_1.createUniversalResponse)({
251
426
  success: true,
252
427
  action: 'prune',
253
- message: `Remotes prunados com sucesso`,
428
+ message: `Remote '${input.name}' pruned successfully`,
254
429
  data: {
255
- remote: params.remote_to_prune,
256
- output: result.output
430
+ remote: input.name,
431
+ dryRun: false,
432
+ pruned: pruneResult.output.trim().split('\n').filter(line => line.trim())
433
+ },
434
+ autoDetected: {
435
+ repo: detection.repoName,
436
+ owner: detection.owner,
437
+ providers: detection.providers
257
438
  }
258
- };
439
+ });
440
+ }
441
+ catch (error) {
442
+ return this.errorHandler.toUniversalResponse();
443
+ }
444
+ }
445
+ }
446
+ /**
447
+ * Tool principal git-remote
448
+ */
449
+ exports.gitRemoteTool = {
450
+ name: 'git-remote',
451
+ description: `🔗 GERENCIAMENTO DE REMOTOS UNIFICADO
452
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
453
+ 🎯 REMOTES INTELIGENTES:
454
+ • add: Adição com auto-detecção de provider
455
+ • remove: Remoção segura com validações
456
+ • rename: Renomeação de remotos
457
+ • show: Informações detalhadas de remotos
458
+ • set-url: Atualização de URLs
459
+ • prune: Limpeza de referências obsoletas
460
+
461
+ 🔍 AUTO-DETECÇÃO:
462
+ • Detecção automática de provider (GitHub/Gitea)
463
+ • Validação de URLs
464
+ • Verificação de conflitos de nomes
465
+ • Sugestões inteligentes de nomes
466
+
467
+ ⚡ OPERAÇÕES SEGUAS:
468
+ • Validação antes de todas as operações
469
+ • Backup de configurações
470
+ • Rollback automático em caso de erro
471
+ • Dry-run para operações destrutivas
472
+
473
+ 🤖 COMPATÍVEL COM AI AGENTS:
474
+ • Interface universal para qualquer IDE
475
+ • Auto-detecção completa de contexto
476
+ • Respostas estruturadas consistentes
477
+ • Error handling inteligente
478
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
479
+ inputSchema: {
480
+ type: 'object',
481
+ properties: {
482
+ action: {
483
+ type: 'string',
484
+ enum: ['add', 'remove', 'rename', 'show', 'set-url', 'prune'],
485
+ description: 'Ação do sistema de remotos'
486
+ },
487
+ projectPath: {
488
+ type: 'string',
489
+ description: 'Caminho absoluto do projeto'
490
+ },
491
+ name: {
492
+ type: 'string',
493
+ description: 'Nome do remote'
494
+ },
495
+ url: {
496
+ type: 'string',
497
+ description: 'URL do remote'
498
+ },
499
+ provider: {
500
+ type: 'string',
501
+ enum: ['gitea', 'github'],
502
+ description: 'Provider específico'
503
+ },
504
+ force: {
505
+ type: 'boolean',
506
+ description: 'Forçar operação'
507
+ },
508
+ oldName: {
509
+ type: 'string',
510
+ description: 'Nome antigo do remote (para rename)'
511
+ },
512
+ newName: {
513
+ type: 'string',
514
+ description: 'Nome novo do remote (para rename)'
515
+ },
516
+ detailed: {
517
+ type: 'boolean',
518
+ description: 'Informações detalhadas'
519
+ },
520
+ push: {
521
+ type: 'boolean',
522
+ description: 'Para push URL diferente'
523
+ },
524
+ dryRun: {
525
+ type: 'boolean',
526
+ description: 'Simular operação sem executar'
527
+ }
528
+ },
529
+ required: ['action', 'projectPath']
530
+ },
531
+ async handler(input) {
532
+ const executor = new GitRemoteExecutor();
533
+ try {
534
+ // Validate input
535
+ const validatedInput = GitRemoteInputSchema.parse(input);
536
+ // Auto-detect context
537
+ const detection = await (0, auto_detection_js_1.autoDetect)(validatedInput.projectPath);
538
+ await (0, auto_detection_js_1.validateAutoDetection)(detection);
539
+ // Execute specific action
540
+ switch (validatedInput.action) {
541
+ case 'add':
542
+ return await executor['executeAdd'](detection, validatedInput);
543
+ case 'remove':
544
+ return await executor['executeRemove'](detection, validatedInput);
545
+ case 'rename':
546
+ return await executor['executeRename'](detection, validatedInput);
547
+ case 'show':
548
+ return await executor['executeShow'](detection, validatedInput);
549
+ case 'set-url':
550
+ return await executor['executeSetUrl'](detection, validatedInput);
551
+ case 'prune':
552
+ return await executor['executePrune'](detection, validatedInput);
553
+ default:
554
+ throw new Error(`Ação '${validatedInput.action}' não suportada`);
555
+ }
259
556
  }
260
557
  catch (error) {
261
- throw new Error(`Falha ao prunar remotes: ${error instanceof Error ? error.message : String(error)}`);
558
+ executor.errorHandler.addError(error);
559
+ return executor.errorHandler.toUniversalResponse();
262
560
  }
263
561
  }
264
562
  };