@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.
- package/README.md +63 -283
- package/dist/providers/base-provider.d.ts.map +1 -1
- package/dist/providers/base-provider.js +3 -26
- package/dist/providers/base-provider.js.map +1 -1
- package/dist/providers/gitea-provider.d.ts +0 -2
- package/dist/providers/gitea-provider.d.ts.map +1 -1
- package/dist/providers/gitea-provider.js +0 -62
- package/dist/providers/gitea-provider.js.map +1 -1
- package/dist/providers/github-provider.d.ts +0 -2
- package/dist/providers/github-provider.d.ts.map +1 -1
- package/dist/providers/github-provider.js +48 -105
- package/dist/providers/github-provider.js.map +1 -1
- package/dist/server.d.ts +0 -27
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +130 -1215
- package/dist/server.js.map +1 -1
- package/dist/tools/{git-commits.d.ts → git-analytics.d.ts} +4 -10
- package/dist/tools/git-analytics.d.ts.map +1 -0
- package/dist/tools/git-analytics.js +18 -0
- package/dist/tools/git-analytics.js.map +1 -0
- package/dist/tools/git-archive.d.ts +3 -0
- package/dist/tools/git-archive.d.ts.map +1 -1
- package/dist/tools/git-archive.js +2 -2
- package/dist/tools/git-archive.js.map +1 -1
- package/dist/tools/git-backup.d.ts +216 -0
- package/dist/tools/git-backup.d.ts.map +1 -0
- package/dist/tools/git-backup.js +813 -0
- package/dist/tools/git-backup.js.map +1 -0
- package/dist/tools/git-branches.d.ts +159 -8
- package/dist/tools/git-branches.d.ts.map +1 -1
- package/dist/tools/git-branches.js +554 -2
- package/dist/tools/git-branches.js.map +1 -1
- package/dist/tools/git-config.d.ts +3 -0
- package/dist/tools/git-config.d.ts.map +1 -1
- package/dist/tools/git-config.js +2 -2
- package/dist/tools/git-config.js.map +1 -1
- package/dist/tools/git-files.d.ts +130 -8
- package/dist/tools/git-files.d.ts.map +1 -1
- package/dist/tools/git-files.js +426 -2
- package/dist/tools/git-files.js.map +1 -1
- package/dist/tools/git-issues.d.ts +137 -471
- package/dist/tools/git-issues.d.ts.map +1 -1
- package/dist/tools/git-issues.js +605 -613
- package/dist/tools/git-issues.js.map +1 -1
- package/dist/tools/git-monitor.d.ts +161 -0
- package/dist/tools/git-monitor.d.ts.map +1 -0
- package/dist/tools/git-monitor.js +746 -0
- package/dist/tools/git-monitor.js.map +1 -0
- package/dist/tools/git-packages.d.ts +5 -2
- package/dist/tools/git-packages.d.ts.map +1 -1
- package/dist/tools/git-packages.js +3 -3
- package/dist/tools/git-packages.js.map +1 -1
- package/dist/tools/git-pulls.d.ts +38 -646
- package/dist/tools/git-pulls.d.ts.map +1 -1
- package/dist/tools/git-pulls.js +64 -716
- package/dist/tools/git-pulls.js.map +1 -1
- package/dist/tools/git-release.d.ts +187 -0
- package/dist/tools/git-release.d.ts.map +1 -0
- package/dist/tools/git-release.js +619 -0
- package/dist/tools/git-release.js.map +1 -0
- package/dist/tools/git-remote.d.ts +112 -77
- package/dist/tools/git-remote.d.ts.map +1 -1
- package/dist/tools/git-remote.js +481 -183
- package/dist/tools/git-remote.js.map +1 -1
- package/dist/tools/git-repos.d.ts +19 -0
- package/dist/tools/git-repos.d.ts.map +1 -0
- package/dist/tools/git-repos.js +18 -0
- package/dist/tools/git-repos.js.map +1 -0
- package/dist/tools/git-reset.d.ts +121 -74
- package/dist/tools/git-reset.d.ts.map +1 -1
- package/dist/tools/git-reset.js +540 -159
- package/dist/tools/git-reset.js.map +1 -1
- package/dist/tools/git-stash.d.ts +119 -78
- package/dist/tools/git-stash.d.ts.map +1 -1
- package/dist/tools/git-stash.js +560 -209
- package/dist/tools/git-stash.js.map +1 -1
- package/dist/tools/git-sync.d.ts +3 -163
- package/dist/tools/git-sync.d.ts.map +1 -1
- package/dist/tools/git-sync.js +9 -326
- package/dist/tools/git-sync.js.map +1 -1
- package/dist/tools/git-tags.d.ts +105 -331
- package/dist/tools/git-tags.d.ts.map +1 -1
- package/dist/tools/git-tags.js +545 -416
- package/dist/tools/git-tags.js.map +1 -1
- package/dist/tools/git-workflow.d.ts +127 -0
- package/dist/tools/git-workflow.d.ts.map +1 -0
- package/dist/tools/git-workflow.js +359 -0
- package/dist/tools/git-workflow.js.map +1 -0
- package/dist/utils/auto-detection.d.ts +113 -0
- package/dist/utils/auto-detection.d.ts.map +1 -0
- package/dist/utils/auto-detection.js +235 -0
- package/dist/utils/auto-detection.js.map +1 -0
- package/dist/utils/error-handler.d.ts +107 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +331 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/git-operations.d.ts.map +1 -1
- package/dist/utils/git-operations.js +6 -51
- package/dist/utils/git-operations.js.map +1 -1
- package/dist/utils/user-detection.d.ts +1 -13
- package/dist/utils/user-detection.d.ts.map +1 -1
- package/dist/utils/user-detection.js +1 -26
- package/dist/utils/user-detection.js.map +1 -1
- package/package.json +60 -60
- package/dist/client.d.ts +0 -307
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -299
- package/dist/client.js.map +0 -1
- package/dist/tools/git-branch-protection.d.ts +0 -97
- package/dist/tools/git-branch-protection.d.ts.map +0 -1
- package/dist/tools/git-branch-protection.js +0 -182
- package/dist/tools/git-branch-protection.js.map +0 -1
- package/dist/tools/git-commits.d.ts.map +0 -1
- package/dist/tools/git-commits.js +0 -5
- package/dist/tools/git-commits.js.map +0 -1
- package/dist/tools/git-initialize.d.ts +0 -208
- package/dist/tools/git-initialize.d.ts.map +0 -1
- package/dist/tools/git-initialize.js +0 -470
- package/dist/tools/git-initialize.js.map +0 -1
- package/dist/tools/git-projects.d.ts +0 -112
- package/dist/tools/git-projects.d.ts.map +0 -1
- package/dist/tools/git-projects.js +0 -319
- package/dist/tools/git-projects.js.map +0 -1
- package/dist/tools/git-releases.d.ts +0 -486
- package/dist/tools/git-releases.d.ts.map +0 -1
- package/dist/tools/git-releases.js +0 -561
- package/dist/tools/git-releases.js.map +0 -1
- package/dist/tools/git-repositories.d.ts +0 -469
- package/dist/tools/git-repositories.d.ts.map +0 -1
- package/dist/tools/git-repositories.js +0 -637
- package/dist/tools/git-repositories.js.map +0 -1
- package/dist/tools/git-revert.d.ts +0 -147
- package/dist/tools/git-revert.d.ts.map +0 -1
- package/dist/tools/git-revert.js +0 -199
- package/dist/tools/git-revert.js.map +0 -1
- package/dist/tools/git-update-project.d.ts +0 -309
- package/dist/tools/git-update-project.d.ts.map +0 -1
- package/dist/tools/git-update-project.js +0 -878
- package/dist/tools/git-update-project.js.map +0 -1
package/dist/tools/git-stash.js
CHANGED
|
@@ -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
|
|
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
|
-
*
|
|
10
|
-
*
|
|
11
|
+
* GERENCIAMENTO DE STASH UNIFICADO
|
|
12
|
+
* Stash inteligente com auto-naming, categorização e recuperação automática
|
|
11
13
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
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.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
118
|
+
index: parseInt(index),
|
|
119
|
+
ref: stashRef,
|
|
120
|
+
exists: true,
|
|
121
|
+
files: files,
|
|
122
|
+
fileCount: files.length
|
|
105
123
|
};
|
|
106
124
|
}
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
111
|
-
if
|
|
112
|
-
|
|
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
|
|
115
|
-
|
|
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 (
|
|
118
|
-
|
|
198
|
+
if (input.keepIndex) {
|
|
199
|
+
args.push('--keep-index');
|
|
119
200
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
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: '
|
|
127
|
-
message:
|
|
212
|
+
action: 'save',
|
|
213
|
+
message: `Changes stashed successfully`,
|
|
128
214
|
data: {
|
|
129
|
-
message:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
229
|
+
return this.errorHandler.toUniversalResponse();
|
|
138
230
|
}
|
|
139
|
-
}
|
|
140
|
-
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Executa operação pop
|
|
234
|
+
*/
|
|
235
|
+
async executePop(detection, input) {
|
|
141
236
|
try {
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
|
|
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@{${
|
|
276
|
+
message: `Stash stash@{${input.index}} applied and removed`,
|
|
156
277
|
data: {
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
|
|
291
|
+
return this.errorHandler.toUniversalResponse();
|
|
164
292
|
}
|
|
165
|
-
}
|
|
166
|
-
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Executa operação apply
|
|
296
|
+
*/
|
|
297
|
+
async executeApply(detection, input) {
|
|
167
298
|
try {
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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
|
-
|
|
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@{${
|
|
338
|
+
message: `Stash stash@{${input.index}} applied (kept in stash)`,
|
|
182
339
|
data: {
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
353
|
+
return this.errorHandler.toUniversalResponse();
|
|
190
354
|
}
|
|
191
|
-
}
|
|
192
|
-
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Executa operação list
|
|
358
|
+
*/
|
|
359
|
+
async executeList(detection, input) {
|
|
193
360
|
try {
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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:
|
|
371
|
+
message: `Found ${filteredStashes.length} stashes`,
|
|
204
372
|
data: {
|
|
205
|
-
stashes:
|
|
206
|
-
|
|
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
|
-
|
|
387
|
+
return this.errorHandler.toUniversalResponse();
|
|
212
388
|
}
|
|
213
|
-
}
|
|
214
|
-
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Executa operação show
|
|
392
|
+
*/
|
|
393
|
+
async executeShow(detection, input) {
|
|
215
394
|
try {
|
|
216
|
-
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
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
|
-
|
|
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@{${
|
|
414
|
+
message: `Stash stash@{${input.index}} details`,
|
|
231
415
|
data: {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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
|
-
|
|
428
|
+
return this.errorHandler.toUniversalResponse();
|
|
240
429
|
}
|
|
241
|
-
}
|
|
242
|
-
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Executa operação drop
|
|
433
|
+
*/
|
|
434
|
+
async executeDrop(detection, input) {
|
|
243
435
|
try {
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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
|
-
|
|
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@{${
|
|
455
|
+
message: `Stash stash@{${input.index}} dropped successfully`,
|
|
258
456
|
data: {
|
|
259
|
-
|
|
260
|
-
|
|
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
|
-
|
|
469
|
+
return this.errorHandler.toUniversalResponse();
|
|
266
470
|
}
|
|
267
|
-
}
|
|
268
|
-
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Executa operação clear
|
|
474
|
+
*/
|
|
475
|
+
async executeClear(detection, input) {
|
|
269
476
|
try {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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:
|
|
506
|
+
message: `All stashes cleared successfully`,
|
|
280
507
|
data: {
|
|
281
|
-
|
|
282
|
-
|
|
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
|
-
|
|
637
|
+
executor.errorHandler.addError(error);
|
|
638
|
+
return executor.errorHandler.toUniversalResponse();
|
|
288
639
|
}
|
|
289
640
|
}
|
|
290
641
|
};
|