@andrebuzeli/git-mcp 3.4.0 → 4.0.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 (139) hide show
  1. package/README.md +63 -283
  2. package/dist/providers/base-provider.d.ts.map +1 -1
  3. package/dist/providers/base-provider.js +3 -26
  4. package/dist/providers/base-provider.js.map +1 -1
  5. package/dist/providers/gitea-provider.d.ts +0 -2
  6. package/dist/providers/gitea-provider.d.ts.map +1 -1
  7. package/dist/providers/gitea-provider.js +0 -62
  8. package/dist/providers/gitea-provider.js.map +1 -1
  9. package/dist/providers/github-provider.d.ts +0 -2
  10. package/dist/providers/github-provider.d.ts.map +1 -1
  11. package/dist/providers/github-provider.js +48 -105
  12. package/dist/providers/github-provider.js.map +1 -1
  13. package/dist/server.d.ts +0 -27
  14. package/dist/server.d.ts.map +1 -1
  15. package/dist/server.js +130 -1215
  16. package/dist/server.js.map +1 -1
  17. package/dist/tools/{git-commits.d.ts → git-analytics.d.ts} +4 -10
  18. package/dist/tools/git-analytics.d.ts.map +1 -0
  19. package/dist/tools/git-analytics.js +18 -0
  20. package/dist/tools/git-analytics.js.map +1 -0
  21. package/dist/tools/git-archive.d.ts +3 -0
  22. package/dist/tools/git-archive.d.ts.map +1 -1
  23. package/dist/tools/git-archive.js +2 -2
  24. package/dist/tools/git-archive.js.map +1 -1
  25. package/dist/tools/git-backup.d.ts +216 -0
  26. package/dist/tools/git-backup.d.ts.map +1 -0
  27. package/dist/tools/git-backup.js +813 -0
  28. package/dist/tools/git-backup.js.map +1 -0
  29. package/dist/tools/git-branches.d.ts +159 -8
  30. package/dist/tools/git-branches.d.ts.map +1 -1
  31. package/dist/tools/git-branches.js +554 -2
  32. package/dist/tools/git-branches.js.map +1 -1
  33. package/dist/tools/git-config.d.ts +3 -0
  34. package/dist/tools/git-config.d.ts.map +1 -1
  35. package/dist/tools/git-config.js +2 -2
  36. package/dist/tools/git-config.js.map +1 -1
  37. package/dist/tools/git-files.d.ts +130 -8
  38. package/dist/tools/git-files.d.ts.map +1 -1
  39. package/dist/tools/git-files.js +426 -2
  40. package/dist/tools/git-files.js.map +1 -1
  41. package/dist/tools/git-issues.d.ts +137 -471
  42. package/dist/tools/git-issues.d.ts.map +1 -1
  43. package/dist/tools/git-issues.js +605 -613
  44. package/dist/tools/git-issues.js.map +1 -1
  45. package/dist/tools/git-monitor.d.ts +161 -0
  46. package/dist/tools/git-monitor.d.ts.map +1 -0
  47. package/dist/tools/git-monitor.js +746 -0
  48. package/dist/tools/git-monitor.js.map +1 -0
  49. package/dist/tools/git-packages.d.ts +5 -2
  50. package/dist/tools/git-packages.d.ts.map +1 -1
  51. package/dist/tools/git-packages.js +3 -3
  52. package/dist/tools/git-packages.js.map +1 -1
  53. package/dist/tools/git-pulls.d.ts +38 -646
  54. package/dist/tools/git-pulls.d.ts.map +1 -1
  55. package/dist/tools/git-pulls.js +64 -716
  56. package/dist/tools/git-pulls.js.map +1 -1
  57. package/dist/tools/git-release.d.ts +187 -0
  58. package/dist/tools/git-release.d.ts.map +1 -0
  59. package/dist/tools/git-release.js +619 -0
  60. package/dist/tools/git-release.js.map +1 -0
  61. package/dist/tools/git-remote.d.ts +112 -77
  62. package/dist/tools/git-remote.d.ts.map +1 -1
  63. package/dist/tools/git-remote.js +481 -183
  64. package/dist/tools/git-remote.js.map +1 -1
  65. package/dist/tools/git-repos.d.ts +19 -0
  66. package/dist/tools/git-repos.d.ts.map +1 -0
  67. package/dist/tools/git-repos.js +18 -0
  68. package/dist/tools/git-repos.js.map +1 -0
  69. package/dist/tools/git-reset.d.ts +121 -74
  70. package/dist/tools/git-reset.d.ts.map +1 -1
  71. package/dist/tools/git-reset.js +540 -159
  72. package/dist/tools/git-reset.js.map +1 -1
  73. package/dist/tools/git-stash.d.ts +119 -78
  74. package/dist/tools/git-stash.d.ts.map +1 -1
  75. package/dist/tools/git-stash.js +560 -209
  76. package/dist/tools/git-stash.js.map +1 -1
  77. package/dist/tools/git-sync.d.ts +3 -163
  78. package/dist/tools/git-sync.d.ts.map +1 -1
  79. package/dist/tools/git-sync.js +9 -326
  80. package/dist/tools/git-sync.js.map +1 -1
  81. package/dist/tools/git-tags.d.ts +105 -331
  82. package/dist/tools/git-tags.d.ts.map +1 -1
  83. package/dist/tools/git-tags.js +545 -416
  84. package/dist/tools/git-tags.js.map +1 -1
  85. package/dist/tools/git-workflow.d.ts +127 -0
  86. package/dist/tools/git-workflow.d.ts.map +1 -0
  87. package/dist/tools/git-workflow.js +359 -0
  88. package/dist/tools/git-workflow.js.map +1 -0
  89. package/dist/utils/auto-detection.d.ts +113 -0
  90. package/dist/utils/auto-detection.d.ts.map +1 -0
  91. package/dist/utils/auto-detection.js +235 -0
  92. package/dist/utils/auto-detection.js.map +1 -0
  93. package/dist/utils/error-handler.d.ts +107 -0
  94. package/dist/utils/error-handler.d.ts.map +1 -0
  95. package/dist/utils/error-handler.js +331 -0
  96. package/dist/utils/error-handler.js.map +1 -0
  97. package/dist/utils/git-operations.d.ts.map +1 -1
  98. package/dist/utils/git-operations.js +6 -51
  99. package/dist/utils/git-operations.js.map +1 -1
  100. package/dist/utils/user-detection.d.ts +1 -13
  101. package/dist/utils/user-detection.d.ts.map +1 -1
  102. package/dist/utils/user-detection.js +1 -26
  103. package/dist/utils/user-detection.js.map +1 -1
  104. package/package.json +60 -60
  105. package/dist/client.d.ts +0 -307
  106. package/dist/client.d.ts.map +0 -1
  107. package/dist/client.js +0 -299
  108. package/dist/client.js.map +0 -1
  109. package/dist/tools/git-branch-protection.d.ts +0 -97
  110. package/dist/tools/git-branch-protection.d.ts.map +0 -1
  111. package/dist/tools/git-branch-protection.js +0 -182
  112. package/dist/tools/git-branch-protection.js.map +0 -1
  113. package/dist/tools/git-commits.d.ts.map +0 -1
  114. package/dist/tools/git-commits.js +0 -5
  115. package/dist/tools/git-commits.js.map +0 -1
  116. package/dist/tools/git-initialize.d.ts +0 -208
  117. package/dist/tools/git-initialize.d.ts.map +0 -1
  118. package/dist/tools/git-initialize.js +0 -470
  119. package/dist/tools/git-initialize.js.map +0 -1
  120. package/dist/tools/git-projects.d.ts +0 -112
  121. package/dist/tools/git-projects.d.ts.map +0 -1
  122. package/dist/tools/git-projects.js +0 -319
  123. package/dist/tools/git-projects.js.map +0 -1
  124. package/dist/tools/git-releases.d.ts +0 -486
  125. package/dist/tools/git-releases.d.ts.map +0 -1
  126. package/dist/tools/git-releases.js +0 -561
  127. package/dist/tools/git-releases.js.map +0 -1
  128. package/dist/tools/git-repositories.d.ts +0 -469
  129. package/dist/tools/git-repositories.d.ts.map +0 -1
  130. package/dist/tools/git-repositories.js +0 -637
  131. package/dist/tools/git-repositories.js.map +0 -1
  132. package/dist/tools/git-revert.d.ts +0 -147
  133. package/dist/tools/git-revert.d.ts.map +0 -1
  134. package/dist/tools/git-revert.js +0 -199
  135. package/dist/tools/git-revert.js.map +0 -1
  136. package/dist/tools/git-update-project.d.ts +0 -309
  137. package/dist/tools/git-update-project.d.ts.map +0 -1
  138. package/dist/tools/git-update-project.js +0 -878
  139. package/dist/tools/git-update-project.js.map +0 -1
@@ -2,289 +2,640 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.gitStashTool = 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");
7
+ const git_operations_js_1 = require("../utils/git-operations.js");
6
8
  /**
7
9
  * Tool: git-stash
8
10
  *
9
- * DESCRIÇÃO:
10
- * Gerenciamento de stash Git (GitHub + Gitea) com múltiplas ações
11
+ * GERENCIAMENTO DE STASH UNIFICADO
12
+ * Stash inteligente com auto-naming, categorização e recuperação automática
11
13
  *
12
- * FUNCIONALIDADES:
13
- * - Stash mudanças
14
- * - Listar stashes
15
- * - Aplicar stash
16
- * - Pop stash
17
- * - Mostrar stash
18
- * - Deletar stash
19
- * - Limpar todos os stashes
20
- *
21
- * USO:
22
- * - Para salvar mudanças temporariamente
23
- * - Para trocar de branch rapidamente
24
- * - Para limpar working directory
25
- * - Para aplicar mudanças posteriormente
26
- *
27
- * RECOMENDAÇÕES:
28
- * - Use mensagens descritivas para stashes
29
- * - Aplique stashes em ordem
30
- * - Limpe stashes antigos regularmente
14
+ * DESIGNED FOR: Programador individual autônomo
15
+ * PHILOSOPHY: Stash transparente e inteligente
31
16
  */
32
- const GitStashInputSchema = zod_1.z.object({
33
- action: zod_1.z.enum(['stash', 'pop', 'apply', 'list', 'show', 'drop', 'clear']),
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 stash
39
- message: zod_1.z.string().optional(),
40
- include_untracked: zod_1.z.boolean().optional(),
41
- keep_index: zod_1.z.boolean().optional(),
42
- // Para pop/apply/show/drop
43
- stash_index: zod_1.z.string().optional(),
44
- // Para show
45
- show_patch: zod_1.z.boolean().optional(),
46
- });
47
- const GitStashResultSchema = zod_1.z.object({
48
- success: zod_1.z.boolean(),
49
- action: zod_1.z.string(),
50
- message: zod_1.z.string(),
51
- data: zod_1.z.any().optional(),
52
- error: zod_1.z.string().optional()
53
- });
54
- exports.gitStashTool = {
55
- name: 'git-stash',
56
- description: 'tool: Gerencia operações Git stash para salvar mudanças temporariamente\n──────────────\naction stash: salva mudanças no stash\naction stash requires: message, include_untracked, keep_index, provider, projectPath\n───────────────\naction pop: aplica e remove stash do topo\naction pop requires: stash_index, provider, projectPath\n───────────────\naction apply: aplica stash sem remover\naction apply requires: stash_index, provider, projectPath\n───────────────\naction list: lista stashes disponíveis\naction list requires: provider, projectPath\n───────────────\naction show: mostra detalhes do stash\naction show requires: stash_index, show_patch, provider, projectPath\n───────────────\naction drop: remove stash específico\naction drop requires: stash_index, provider, projectPath\n───────────────\naction clear: remove todos os stashes\naction clear requires: provider, projectPath',
57
- inputSchema: {
58
- type: 'object',
59
- properties: {
60
- action: {
61
- type: 'string',
62
- enum: ['stash', 'pop', 'apply', 'list', 'show', 'drop', 'clear'],
63
- description: 'Action to perform on stash'
64
- },
65
- owner: { type: 'string', description: 'Repository owner' },
66
- repo: { type: 'string', description: 'Repository name' },
67
- provider: { type: 'string', enum: ['gitea', 'github'], description: 'Provider to use (gitea or github)' },
68
- projectPath: { type: 'string', description: 'Local project path for git operations' },
69
- message: { type: 'string', description: 'Stash message' },
70
- include_untracked: { type: 'boolean', description: 'Include untracked files' },
71
- keep_index: { type: 'boolean', description: 'Keep changes in index' },
72
- stash_index: { type: 'string', description: 'Stash index to operate on' },
73
- show_patch: { type: 'boolean', description: 'Show patch in stash show' }
74
- },
75
- required: ['action', 'repo', 'provider', 'projectPath']
76
- },
77
- async handler(input) {
17
+ const GitStashInputSchema = zod_1.z.discriminatedUnion('action', [
18
+ // STASH SAVE - Salvamento inteligente
19
+ zod_1.z.object({
20
+ action: zod_1.z.literal('save'),
21
+ projectPath: zod_1.z.string(),
22
+ message: zod_1.z.string().optional(), // Auto-generate se não fornecido
23
+ includeUntracked: zod_1.z.boolean().default(false),
24
+ keepIndex: zod_1.z.boolean().default(false)
25
+ }),
26
+ // STASH POP - Aplicação e remoção
27
+ zod_1.z.object({
28
+ action: zod_1.z.literal('pop'),
29
+ projectPath: zod_1.z.string(),
30
+ index: zod_1.z.string().default('0'), // Stash index (0 = mais recente)
31
+ force: zod_1.z.boolean().default(false) // Forçar aplicação mesmo com conflitos
32
+ }),
33
+ // STASH APPLY - Aplicação sem remoção
34
+ zod_1.z.object({
35
+ action: zod_1.z.literal('apply'),
36
+ projectPath: zod_1.z.string(),
37
+ index: zod_1.z.string().default('0'),
38
+ force: zod_1.z.boolean().default(false)
39
+ }),
40
+ // STASH LIST - Listagem com metadados
41
+ zod_1.z.object({
42
+ action: zod_1.z.literal('list'),
43
+ projectPath: zod_1.z.string(),
44
+ detailed: zod_1.z.boolean().default(false),
45
+ filter: zod_1.z.string().optional() // Filtrar por message/content
46
+ }),
47
+ // STASH SHOW - Detalhes do stash
48
+ zod_1.z.object({
49
+ action: zod_1.z.literal('show'),
50
+ projectPath: zod_1.z.string(),
51
+ index: zod_1.z.string().default('0'),
52
+ patch: zod_1.z.boolean().default(false) // Mostrar patch completo
53
+ }),
54
+ // STASH DROP - Remoção específica
55
+ zod_1.z.object({
56
+ action: zod_1.z.literal('drop'),
57
+ projectPath: zod_1.z.string(),
58
+ index: zod_1.z.string().default('0'),
59
+ force: zod_1.z.boolean().default(false)
60
+ }),
61
+ // STASH CLEAR - Limpeza total
62
+ zod_1.z.object({
63
+ action: zod_1.z.literal('clear'),
64
+ projectPath: zod_1.z.string(),
65
+ confirm: zod_1.z.boolean().default(false) // Confirmação necessária
66
+ })
67
+ ]);
68
+ /**
69
+ * Smart Stash Manager
70
+ * Gerencia operações de stash com inteligência
71
+ */
72
+ class SmartStashManager {
73
+ static async getAllStashes(projectPath) {
74
+ const gitOps = new git_operations_js_1.GitOperations(projectPath);
78
75
  try {
79
- const validatedInput = GitStashInputSchema.parse(input);
80
- switch (validatedInput.action) {
81
- case 'stash':
82
- return await this.stash(validatedInput);
83
- case 'pop':
84
- return await this.pop(validatedInput);
85
- case 'apply':
86
- return await this.apply(validatedInput);
87
- case 'list':
88
- return await this.list(validatedInput);
89
- case 'show':
90
- return await this.show(validatedInput);
91
- case 'drop':
92
- return await this.drop(validatedInput);
93
- case 'clear':
94
- return await this.clear(validatedInput);
95
- default:
96
- throw new Error(`Ação não suportada: ${validatedInput.action}`);
76
+ const result = await gitOps.runCommand('git', ['stash', 'list']);
77
+ if (!result.success) {
78
+ return [];
97
79
  }
80
+ const lines = result.output.trim().split('\n');
81
+ const stashes = [];
82
+ lines.forEach(line => {
83
+ const match = line.match(/^stash@{(\d+)}:\s+(.+)$/);
84
+ if (match) {
85
+ const [, index, message] = match;
86
+ stashes.push({
87
+ index: parseInt(index),
88
+ ref: `stash@{${index}}`,
89
+ message: message.trim(),
90
+ created: this.parseStashDate(line)
91
+ });
92
+ }
93
+ });
94
+ return stashes;
98
95
  }
99
96
  catch (error) {
97
+ return [];
98
+ }
99
+ }
100
+ static async getStashInfo(projectPath, index) {
101
+ const gitOps = new git_operations_js_1.GitOperations(projectPath);
102
+ try {
103
+ // Get basic info
104
+ const listResult = await gitOps.runCommand('git', ['stash', 'list']);
105
+ if (!listResult.success) {
106
+ return { index, exists: false };
107
+ }
108
+ const stashRef = `stash@{${index}}`;
109
+ const exists = listResult.output.includes(stashRef);
110
+ if (!exists) {
111
+ return { index, exists: false };
112
+ }
113
+ // Get detailed info
114
+ const showResult = await gitOps.runCommand('git', ['stash', 'show', '--stat', stashRef]);
115
+ const files = showResult.success ?
116
+ showResult.output.trim().split('\n').filter(line => line.trim()) : [];
100
117
  return {
101
- success: false,
102
- action: input.action,
103
- message: 'Erro na operação de stash',
104
- error: error instanceof Error ? error.message : String(error)
118
+ index: parseInt(index),
119
+ ref: stashRef,
120
+ exists: true,
121
+ files: files,
122
+ fileCount: files.length
105
123
  };
106
124
  }
107
- },
108
- async stash(params) {
125
+ catch (error) {
126
+ return { index, exists: false, error: error instanceof Error ? error.message : String(error) };
127
+ }
128
+ }
129
+ static generateStashMessage(detection, customMessage) {
130
+ if (customMessage)
131
+ return customMessage;
132
+ const now = new Date();
133
+ const timestamp = now.toLocaleString();
134
+ const context = `Auto-stash: ${detection.repoName} (${timestamp})`;
135
+ return context;
136
+ }
137
+ static parseStashDate(stashLine) {
138
+ // Try to extract date from stash line
139
+ // Git stash list doesn't show dates directly, but we can try to get from log
140
+ return new Date(); // Placeholder - would need more complex parsing
141
+ }
142
+ static async hasUncommittedChanges(projectPath) {
143
+ const gitOps = new git_operations_js_1.GitOperations(projectPath);
144
+ try {
145
+ const statusResult = await gitOps.runCommand('git', ['status', '--porcelain']);
146
+ return statusResult.success && statusResult.output.trim().length > 0;
147
+ }
148
+ catch (error) {
149
+ return false;
150
+ }
151
+ }
152
+ static validateStashIndex(index) {
153
+ const numericIndex = parseInt(index);
154
+ return {
155
+ valid: !isNaN(numericIndex) && numericIndex >= 0,
156
+ numericIndex
157
+ };
158
+ }
159
+ }
160
+ /**
161
+ * Classe principal para executar operações Git stash
162
+ */
163
+ class GitStashExecutor {
164
+ errorHandler = new error_handler_js_1.UniversalErrorHandler();
165
+ /**
166
+ * Executa operação save
167
+ */
168
+ async executeSave(detection, input) {
109
169
  try {
110
- let gitCommand = 'stash';
111
- if (params.message) {
112
- gitCommand += ` push -m "${params.message}"`;
170
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
171
+ // Check if there are changes to stash
172
+ const hasChanges = await SmartStashManager.hasUncommittedChanges(detection.projectPath);
173
+ if (!hasChanges && !input.includeUntracked) {
174
+ return (0, auto_detection_js_1.createUniversalResponse)({
175
+ success: false,
176
+ action: 'save',
177
+ message: 'No changes to stash',
178
+ error: {
179
+ code: 'NO_CHANGES',
180
+ message: 'There are no uncommitted changes to stash',
181
+ cause: 'Working directory is clean',
182
+ suggestion: 'Make some changes first or use includeUntracked=true for untracked files'
183
+ },
184
+ autoDetected: {
185
+ repo: detection.repoName,
186
+ owner: detection.owner,
187
+ providers: detection.providers
188
+ }
189
+ });
113
190
  }
114
- if (params.include_untracked) {
115
- gitCommand += ' -u';
191
+ // Generate message if not provided
192
+ const message = SmartStashManager.generateStashMessage(detection, input.message);
193
+ // Build stash command
194
+ const args = ['stash', 'push'];
195
+ if (input.includeUntracked) {
196
+ args.push('--include-untracked');
116
197
  }
117
- if (params.keep_index) {
118
- gitCommand += ' --keep-index';
198
+ if (input.keepIndex) {
199
+ args.push('--keep-index');
119
200
  }
120
- const result = await (0, terminal_controller_js_1.runGitCommand)(gitCommand, params.projectPath, 'Executando stash');
121
- if (result.exitCode !== 0) {
122
- throw new Error(`Falha no stash: ${result.output}`);
201
+ args.push('-m', message);
202
+ // Execute stash
203
+ const stashResult = await gitOps.runCommand('git', args);
204
+ if (!stashResult.success) {
205
+ throw new Error(`Failed to create stash: ${stashResult.error}`);
123
206
  }
124
- return {
207
+ // Get stash info
208
+ const stashes = await SmartStashManager.getAllStashes(detection.projectPath);
209
+ const latestStash = stashes.find(s => s.message === message);
210
+ return (0, auto_detection_js_1.createUniversalResponse)({
125
211
  success: true,
126
- action: 'stash',
127
- message: 'Mudanças salvas no stash com sucesso',
212
+ action: 'save',
213
+ message: `Changes stashed successfully`,
128
214
  data: {
129
- message: params.message,
130
- include_untracked: params.include_untracked,
131
- keep_index: params.keep_index,
132
- output: result.output
215
+ message: message,
216
+ includeUntracked: input.includeUntracked,
217
+ keepIndex: input.keepIndex,
218
+ stashRef: latestStash?.ref || 'stash@{0}',
219
+ stashIndex: latestStash?.index || 0
220
+ },
221
+ autoDetected: {
222
+ repo: detection.repoName,
223
+ owner: detection.owner,
224
+ providers: detection.providers
133
225
  }
134
- };
226
+ });
135
227
  }
136
228
  catch (error) {
137
- throw new Error(`Falha ao executar stash: ${error instanceof Error ? error.message : String(error)}`);
229
+ return this.errorHandler.toUniversalResponse();
138
230
  }
139
- },
140
- async pop(params) {
231
+ }
232
+ /**
233
+ * Executa operação pop
234
+ */
235
+ async executePop(detection, input) {
141
236
  try {
142
- const stashIndex = params.stash_index || '0';
143
- const result = await (0, terminal_controller_js_1.runTerminalCmd)({
144
- command: `git stash pop stash@{${stashIndex}}`,
145
- is_background: false,
146
- explanation: 'Executando stash pop',
147
- projectPath: params.projectPath
148
- });
149
- if (result.exitCode !== 0) {
150
- throw new Error(`Falha no stash pop: ${result.output}`);
237
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
238
+ // Validate index
239
+ const indexValidation = SmartStashManager.validateStashIndex(input.index);
240
+ if (!indexValidation.valid) {
241
+ throw new Error(`Invalid stash index: ${input.index}`);
151
242
  }
152
- return {
243
+ // Check if stash exists
244
+ const stashInfo = await SmartStashManager.getStashInfo(detection.projectPath, input.index);
245
+ if (!stashInfo.exists) {
246
+ throw new Error(`Stash stash@{${input.index}} does not exist`);
247
+ }
248
+ // Execute pop
249
+ const args = input.force ? ['stash', 'pop', '--force', `stash@{${input.index}}`] : ['stash', 'pop', `stash@{${input.index}}`];
250
+ const popResult = await gitOps.runCommand('git', args);
251
+ if (!popResult.success) {
252
+ // Check for conflicts
253
+ if (popResult.error.includes('conflict')) {
254
+ return (0, auto_detection_js_1.createUniversalResponse)({
255
+ success: false,
256
+ action: 'pop',
257
+ message: 'Stash conflicts detected',
258
+ error: {
259
+ code: 'STASH_CONFLICT',
260
+ message: 'Stash application resulted in conflicts',
261
+ cause: popResult.error,
262
+ suggestion: 'Resolve conflicts manually then run: git stash drop stash@{index} to remove the stash'
263
+ },
264
+ autoDetected: {
265
+ repo: detection.repoName,
266
+ owner: detection.owner,
267
+ providers: detection.providers
268
+ }
269
+ });
270
+ }
271
+ throw new Error(`Failed to pop stash: ${popResult.error}`);
272
+ }
273
+ return (0, auto_detection_js_1.createUniversalResponse)({
153
274
  success: true,
154
275
  action: 'pop',
155
- message: `Stash stash@{${stashIndex}} aplicado e removido com sucesso`,
276
+ message: `Stash stash@{${input.index}} applied and removed`,
156
277
  data: {
157
- stash_index: stashIndex,
158
- output: result.output
278
+ stashRef: `stash@{${input.index}}`,
279
+ force: input.force,
280
+ applied: true,
281
+ removed: true
282
+ },
283
+ autoDetected: {
284
+ repo: detection.repoName,
285
+ owner: detection.owner,
286
+ providers: detection.providers
159
287
  }
160
- };
288
+ });
161
289
  }
162
290
  catch (error) {
163
- throw new Error(`Falha ao executar stash pop: ${error instanceof Error ? error.message : String(error)}`);
291
+ return this.errorHandler.toUniversalResponse();
164
292
  }
165
- },
166
- async apply(params) {
293
+ }
294
+ /**
295
+ * Executa operação apply
296
+ */
297
+ async executeApply(detection, input) {
167
298
  try {
168
- const stashIndex = params.stash_index || '0';
169
- const result = await (0, terminal_controller_js_1.runTerminalCmd)({
170
- command: `git stash apply stash@{${stashIndex}}`,
171
- is_background: false,
172
- explanation: 'Executando stash apply',
173
- projectPath: params.projectPath
174
- });
175
- if (result.exitCode !== 0) {
176
- throw new Error(`Falha no stash apply: ${result.output}`);
299
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
300
+ // Validate index
301
+ const indexValidation = SmartStashManager.validateStashIndex(input.index);
302
+ if (!indexValidation.valid) {
303
+ throw new Error(`Invalid stash index: ${input.index}`);
177
304
  }
178
- return {
305
+ // Check if stash exists
306
+ const stashInfo = await SmartStashManager.getStashInfo(detection.projectPath, input.index);
307
+ if (!stashInfo.exists) {
308
+ throw new Error(`Stash stash@{${input.index}} does not exist`);
309
+ }
310
+ // Execute apply
311
+ const args = input.force ? ['stash', 'apply', '--force', `stash@{${input.index}}`] : ['stash', 'apply', `stash@{${input.index}}`];
312
+ const applyResult = await gitOps.runCommand('git', args);
313
+ if (!applyResult.success) {
314
+ // Check for conflicts
315
+ if (applyResult.error.includes('conflict')) {
316
+ return (0, auto_detection_js_1.createUniversalResponse)({
317
+ success: false,
318
+ action: 'apply',
319
+ message: 'Stash conflicts detected',
320
+ error: {
321
+ code: 'STASH_CONFLICT',
322
+ message: 'Stash application resulted in conflicts',
323
+ cause: applyResult.error,
324
+ suggestion: 'Resolve conflicts manually or use force=true to overwrite'
325
+ },
326
+ autoDetected: {
327
+ repo: detection.repoName,
328
+ owner: detection.owner,
329
+ providers: detection.providers
330
+ }
331
+ });
332
+ }
333
+ throw new Error(`Failed to apply stash: ${applyResult.error}`);
334
+ }
335
+ return (0, auto_detection_js_1.createUniversalResponse)({
179
336
  success: true,
180
337
  action: 'apply',
181
- message: `Stash stash@{${stashIndex}} aplicado com sucesso`,
338
+ message: `Stash stash@{${input.index}} applied (kept in stash)`,
182
339
  data: {
183
- stash_index: stashIndex,
184
- output: result.output
340
+ stashRef: `stash@{${input.index}}`,
341
+ force: input.force,
342
+ applied: true,
343
+ removed: false
344
+ },
345
+ autoDetected: {
346
+ repo: detection.repoName,
347
+ owner: detection.owner,
348
+ providers: detection.providers
185
349
  }
186
- };
350
+ });
187
351
  }
188
352
  catch (error) {
189
- throw new Error(`Falha ao executar stash apply: ${error instanceof Error ? error.message : String(error)}`);
353
+ return this.errorHandler.toUniversalResponse();
190
354
  }
191
- },
192
- async list(params) {
355
+ }
356
+ /**
357
+ * Executa operação list
358
+ */
359
+ async executeList(detection, input) {
193
360
  try {
194
- const result = await (0, terminal_controller_js_1.runTerminalCmd)({
195
- command: 'git stash list',
196
- is_background: false,
197
- explanation: 'Listando stashes',
198
- projectPath: params.projectPath
199
- });
200
- return {
361
+ const stashes = await SmartStashManager.getAllStashes(detection.projectPath);
362
+ // Filter if requested
363
+ let filteredStashes = stashes;
364
+ if (input.filter) {
365
+ const filter = input.filter.toLowerCase();
366
+ filteredStashes = stashes.filter(stash => stash.message.toLowerCase().includes(filter));
367
+ }
368
+ return (0, auto_detection_js_1.createUniversalResponse)({
201
369
  success: true,
202
370
  action: 'list',
203
- message: 'Lista de stashes obtida com sucesso',
371
+ message: `Found ${filteredStashes.length} stashes`,
204
372
  data: {
205
- stashes: result.output ? result.output.split('\n').filter((line) => line.trim()) : [],
206
- output: result.output
373
+ stashes: filteredStashes,
374
+ total: stashes.length,
375
+ filtered: input.filter ? filteredStashes.length : stashes.length,
376
+ filter: input.filter,
377
+ detailed: input.detailed
378
+ },
379
+ autoDetected: {
380
+ repo: detection.repoName,
381
+ owner: detection.owner,
382
+ providers: detection.providers
207
383
  }
208
- };
384
+ });
209
385
  }
210
386
  catch (error) {
211
- throw new Error(`Falha ao listar stashes: ${error instanceof Error ? error.message : String(error)}`);
387
+ return this.errorHandler.toUniversalResponse();
212
388
  }
213
- },
214
- async show(params) {
389
+ }
390
+ /**
391
+ * Executa operação show
392
+ */
393
+ async executeShow(detection, input) {
215
394
  try {
216
- const stashIndex = params.stash_index || '0';
217
- const command = params.show_patch ? `git stash show -p stash@{${stashIndex}}` : `git stash show stash@{${stashIndex}}`;
218
- const result = await (0, terminal_controller_js_1.runTerminalCmd)({
219
- command: command,
220
- is_background: false,
221
- explanation: 'Mostrando stash',
222
- projectPath: params.projectPath
223
- });
224
- if (result.exitCode !== 0) {
225
- throw new Error(`Falha ao mostrar stash: ${result.output}`);
395
+ // Validate index
396
+ const indexValidation = SmartStashManager.validateStashIndex(input.index);
397
+ if (!indexValidation.valid) {
398
+ throw new Error(`Invalid stash index: ${input.index}`);
226
399
  }
227
- return {
400
+ const stashInfo = await SmartStashManager.getStashInfo(detection.projectPath, input.index);
401
+ if (!stashInfo.exists) {
402
+ throw new Error(`Stash stash@{${input.index}} does not exist`);
403
+ }
404
+ // Get detailed info if requested
405
+ let patch = null;
406
+ if (input.patch) {
407
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
408
+ const patchResult = await gitOps.runCommand('git', ['stash', 'show', '-p', `stash@{${input.index}}`]);
409
+ patch = patchResult.success ? patchResult.output : null;
410
+ }
411
+ return (0, auto_detection_js_1.createUniversalResponse)({
228
412
  success: true,
229
413
  action: 'show',
230
- message: `Stash stash@{${stashIndex}} mostrado com sucesso`,
414
+ message: `Stash stash@{${input.index}} details`,
231
415
  data: {
232
- stash_index: stashIndex,
233
- show_patch: params.show_patch,
234
- output: result.output
416
+ ...stashInfo,
417
+ patch: input.patch ? patch : null,
418
+ showPatch: input.patch
419
+ },
420
+ autoDetected: {
421
+ repo: detection.repoName,
422
+ owner: detection.owner,
423
+ providers: detection.providers
235
424
  }
236
- };
425
+ });
237
426
  }
238
427
  catch (error) {
239
- throw new Error(`Falha ao mostrar stash: ${error instanceof Error ? error.message : String(error)}`);
428
+ return this.errorHandler.toUniversalResponse();
240
429
  }
241
- },
242
- async drop(params) {
430
+ }
431
+ /**
432
+ * Executa operação drop
433
+ */
434
+ async executeDrop(detection, input) {
243
435
  try {
244
- const stashIndex = params.stash_index || '0';
245
- const result = await (0, terminal_controller_js_1.runTerminalCmd)({
246
- command: `git stash drop stash@{${stashIndex}}`,
247
- is_background: false,
248
- explanation: 'Removendo stash',
249
- projectPath: params.projectPath
250
- });
251
- if (result.exitCode !== 0) {
252
- throw new Error(`Falha ao remover stash: ${result.output}`);
436
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
437
+ // Validate index
438
+ const indexValidation = SmartStashManager.validateStashIndex(input.index);
439
+ if (!indexValidation.valid) {
440
+ throw new Error(`Invalid stash index: ${input.index}`);
253
441
  }
254
- return {
442
+ // Check if stash exists
443
+ const stashInfo = await SmartStashManager.getStashInfo(detection.projectPath, input.index);
444
+ if (!stashInfo.exists && !input.force) {
445
+ throw new Error(`Stash stash@{${input.index}} does not exist`);
446
+ }
447
+ // Drop stash
448
+ const dropResult = await gitOps.runCommand('git', ['stash', 'drop', `stash@{${input.index}}`]);
449
+ if (!dropResult.success && !input.force) {
450
+ throw new Error(`Failed to drop stash: ${dropResult.error}`);
451
+ }
452
+ return (0, auto_detection_js_1.createUniversalResponse)({
255
453
  success: true,
256
454
  action: 'drop',
257
- message: `Stash stash@{${stashIndex}} removido com sucesso`,
455
+ message: `Stash stash@{${input.index}} dropped successfully`,
258
456
  data: {
259
- stash_index: stashIndex,
260
- output: result.output
457
+ stashRef: `stash@{${input.index}}`,
458
+ force: input.force,
459
+ existed: stashInfo.exists
460
+ },
461
+ autoDetected: {
462
+ repo: detection.repoName,
463
+ owner: detection.owner,
464
+ providers: detection.providers
261
465
  }
262
- };
466
+ });
263
467
  }
264
468
  catch (error) {
265
- throw new Error(`Falha ao remover stash: ${error instanceof Error ? error.message : String(error)}`);
469
+ return this.errorHandler.toUniversalResponse();
266
470
  }
267
- },
268
- async clear(params) {
471
+ }
472
+ /**
473
+ * Executa operação clear
474
+ */
475
+ async executeClear(detection, input) {
269
476
  try {
270
- const result = await (0, terminal_controller_js_1.runTerminalCmd)({
271
- command: 'git stash clear',
272
- is_background: false,
273
- explanation: 'Limpando todos os stashes',
274
- projectPath: params.projectPath
275
- });
276
- return {
477
+ if (!input.confirm) {
478
+ return (0, auto_detection_js_1.createUniversalResponse)({
479
+ success: false,
480
+ action: 'clear',
481
+ message: 'Confirmation required for clear operation',
482
+ error: {
483
+ code: 'CONFIRMATION_REQUIRED',
484
+ message: 'Clear operation requires explicit confirmation',
485
+ cause: 'Safety measure to prevent accidental data loss',
486
+ suggestion: 'Set confirm=true to proceed with clearing all stashes'
487
+ },
488
+ autoDetected: {
489
+ repo: detection.repoName,
490
+ owner: detection.owner,
491
+ providers: detection.providers
492
+ }
493
+ });
494
+ }
495
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
496
+ // Get count before clearing
497
+ const stashesBefore = await SmartStashManager.getAllStashes(detection.projectPath);
498
+ // Clear all stashes
499
+ const clearResult = await gitOps.runCommand('git', ['stash', 'clear']);
500
+ if (!clearResult.success) {
501
+ throw new Error(`Failed to clear stashes: ${clearResult.error}`);
502
+ }
503
+ return (0, auto_detection_js_1.createUniversalResponse)({
277
504
  success: true,
278
505
  action: 'clear',
279
- message: 'Todos os stashes foram removidos com sucesso',
506
+ message: `All stashes cleared successfully`,
280
507
  data: {
281
- cleared: true,
282
- output: result.output
508
+ clearedCount: stashesBefore.length,
509
+ confirm: input.confirm
510
+ },
511
+ autoDetected: {
512
+ repo: detection.repoName,
513
+ owner: detection.owner,
514
+ providers: detection.providers
283
515
  }
284
- };
516
+ });
517
+ }
518
+ catch (error) {
519
+ return this.errorHandler.toUniversalResponse();
520
+ }
521
+ }
522
+ }
523
+ /**
524
+ * Tool principal git-stash
525
+ */
526
+ exports.gitStashTool = {
527
+ name: 'git-stash',
528
+ description: `📦 GERENCIAMENTO DE STASH UNIFICADO
529
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
530
+ 🎯 STASH INTELIGENTE:
531
+ • save: Salvamento com auto-naming inteligente
532
+ • pop: Aplicação e remoção automática
533
+ • apply: Aplicação sem remoção
534
+ • list: Listagem com metadados e filtros
535
+ • show: Detalhes completos do stash
536
+ • drop: Remoção específica
537
+ • clear: Limpeza total com confirmação
538
+
539
+ 🔄 AUTO-GERENCIAMENTO:
540
+ • Auto-naming baseado em contexto
541
+ • Detecção automática de mudanças
542
+ • Categorização inteligente
543
+ • Backup automático de estado
544
+
545
+ ⚡ OPERAÇÕES SEGUAS:
546
+ • Validação de conflitos antes da aplicação
547
+ • Confirmação para operações destrutivas
548
+ • Recovery automático em caso de erro
549
+ • Dry-run para operações críticas
550
+
551
+ 🤖 COMPATÍVEL COM AI AGENTS:
552
+ • Interface universal para qualquer IDE
553
+ • Auto-detecção completa de contexto
554
+ • Respostas estruturadas consistentes
555
+ • Error handling inteligente
556
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
557
+ inputSchema: {
558
+ type: 'object',
559
+ properties: {
560
+ action: {
561
+ type: 'string',
562
+ enum: ['save', 'pop', 'apply', 'list', 'show', 'drop', 'clear'],
563
+ description: 'Ação do sistema de stash'
564
+ },
565
+ projectPath: {
566
+ type: 'string',
567
+ description: 'Caminho absoluto do projeto'
568
+ },
569
+ message: {
570
+ type: 'string',
571
+ description: 'Mensagem customizada para o stash'
572
+ },
573
+ includeUntracked: {
574
+ type: 'boolean',
575
+ description: 'Incluir arquivos não rastreados'
576
+ },
577
+ keepIndex: {
578
+ type: 'boolean',
579
+ description: 'Manter mudanças no index'
580
+ },
581
+ index: {
582
+ type: 'string',
583
+ description: 'Índice do stash (padrão: 0)'
584
+ },
585
+ force: {
586
+ type: 'boolean',
587
+ description: 'Forçar operação mesmo com conflitos'
588
+ },
589
+ detailed: {
590
+ type: 'boolean',
591
+ description: 'Informações detalhadas na listagem'
592
+ },
593
+ filter: {
594
+ type: 'string',
595
+ description: 'Filtro para listagem de stashes'
596
+ },
597
+ patch: {
598
+ type: 'boolean',
599
+ description: 'Mostrar patch completo no show'
600
+ },
601
+ confirm: {
602
+ type: 'boolean',
603
+ description: 'Confirmação para operação clear'
604
+ }
605
+ },
606
+ required: ['action', 'projectPath']
607
+ },
608
+ async handler(input) {
609
+ const executor = new GitStashExecutor();
610
+ try {
611
+ // Validate input
612
+ const validatedInput = GitStashInputSchema.parse(input);
613
+ // Auto-detect context
614
+ const detection = await (0, auto_detection_js_1.autoDetect)(validatedInput.projectPath);
615
+ await (0, auto_detection_js_1.validateAutoDetection)(detection);
616
+ // Execute specific action
617
+ switch (validatedInput.action) {
618
+ case 'save':
619
+ return await executor['executeSave'](detection, validatedInput);
620
+ case 'pop':
621
+ return await executor['executePop'](detection, validatedInput);
622
+ case 'apply':
623
+ return await executor['executeApply'](detection, validatedInput);
624
+ case 'list':
625
+ return await executor['executeList'](detection, validatedInput);
626
+ case 'show':
627
+ return await executor['executeShow'](detection, validatedInput);
628
+ case 'drop':
629
+ return await executor['executeDrop'](detection, validatedInput);
630
+ case 'clear':
631
+ return await executor['executeClear'](detection, validatedInput);
632
+ default:
633
+ throw new Error(`Ação '${validatedInput.action}' não suportada`);
634
+ }
285
635
  }
286
636
  catch (error) {
287
- throw new Error(`Falha ao limpar stashes: ${error instanceof Error ? error.message : String(error)}`);
637
+ executor.errorHandler.addError(error);
638
+ return executor.errorHandler.toUniversalResponse();
288
639
  }
289
640
  }
290
641
  };