@andre.buzeli/git-mcp 16.0.1 → 16.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.
package/package.json
CHANGED
|
@@ -146,14 +146,51 @@ export class ProviderManager {
|
|
|
146
146
|
if (createIfMissing) {
|
|
147
147
|
let cr;
|
|
148
148
|
if (organization) {
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
149
|
+
// Tentar criar repo na organização
|
|
150
|
+
try {
|
|
151
|
+
cr = await this.github.rest.repos.createInOrg({
|
|
152
|
+
org: organization,
|
|
153
|
+
name: repoName,
|
|
154
|
+
description,
|
|
155
|
+
private: isPrivate,
|
|
156
|
+
auto_init: false,
|
|
157
|
+
});
|
|
158
|
+
} catch (orgRepoErr) {
|
|
159
|
+
const errMsg = String(orgRepoErr?.message || orgRepoErr).toLowerCase();
|
|
160
|
+
// Se org não existe, criar a org primeiro e depois o repo
|
|
161
|
+
if (errMsg.includes("not found") || errMsg.includes("404")) {
|
|
162
|
+
console.error(`[ProviderManager] GitHub org '${organization}' not found, creating...`);
|
|
163
|
+
try {
|
|
164
|
+
await this.github.rest.orgs.createForAuthenticatedUser
|
|
165
|
+
? await this.github.request("POST /user/orgs", { login: organization, profile_name: organization })
|
|
166
|
+
: null;
|
|
167
|
+
} catch (orgCreateErr) {
|
|
168
|
+
// GitHub free users can't create orgs via API, try alternative
|
|
169
|
+
console.error(`[ProviderManager] GitHub org creation failed: ${orgCreateErr?.message}. Trying as user repo with org topic...`);
|
|
170
|
+
}
|
|
171
|
+
// Retry repo creation in org
|
|
172
|
+
try {
|
|
173
|
+
cr = await this.github.rest.repos.createInOrg({
|
|
174
|
+
org: organization,
|
|
175
|
+
name: repoName,
|
|
176
|
+
description,
|
|
177
|
+
private: isPrivate,
|
|
178
|
+
auto_init: false,
|
|
179
|
+
});
|
|
180
|
+
} catch {
|
|
181
|
+
// Fallback: create as personal repo if org creation not possible
|
|
182
|
+
console.error(`[ProviderManager] Fallback: creating '${repoName}' as personal repo (GitHub org '${organization}' unavailable)`);
|
|
183
|
+
cr = await this.github.rest.repos.createForAuthenticatedUser({
|
|
184
|
+
name: repoName,
|
|
185
|
+
description: `[org:${organization}] ${description}`,
|
|
186
|
+
private: isPrivate,
|
|
187
|
+
auto_init: false,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
} else {
|
|
191
|
+
throw orgRepoErr;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
157
194
|
} else {
|
|
158
195
|
// Criar repo no usuário pessoal
|
|
159
196
|
cr = await this.github.rest.repos.createForAuthenticatedUser({
|
|
@@ -187,9 +224,34 @@ export class ProviderManager {
|
|
|
187
224
|
} catch (e) {
|
|
188
225
|
if (createIfMissing) {
|
|
189
226
|
try {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
227
|
+
let createUrl;
|
|
228
|
+
if (organization) {
|
|
229
|
+
// Verificar se org existe, criar se não existir
|
|
230
|
+
try {
|
|
231
|
+
await axios.get(`${this.giteaUrl}/api/v1/orgs/${organization}`,
|
|
232
|
+
{ headers: { Authorization: `token ${this.giteaToken}` }, timeout: 8000 });
|
|
233
|
+
} catch (orgCheckErr) {
|
|
234
|
+
// Org não existe, criar
|
|
235
|
+
console.error(`[ProviderManager] Gitea org '${organization}' not found, creating...`);
|
|
236
|
+
try {
|
|
237
|
+
await axios.post(`${this.giteaUrl}/api/v1/orgs`, {
|
|
238
|
+
username: organization,
|
|
239
|
+
full_name: organization,
|
|
240
|
+
description: `Organization ${organization}`,
|
|
241
|
+
visibility: isPublic ? "public" : "limited",
|
|
242
|
+
}, { headers: { Authorization: `token ${this.giteaToken}` }, timeout: 8000 });
|
|
243
|
+
console.error(`[ProviderManager] Gitea org '${organization}' created successfully`);
|
|
244
|
+
} catch (orgCreateErr) {
|
|
245
|
+
const msg = String(orgCreateErr?.message || orgCreateErr).toLowerCase();
|
|
246
|
+
if (!msg.includes("already exists") && !msg.includes("409")) {
|
|
247
|
+
console.error(`[ProviderManager] Gitea org creation failed: ${orgCreateErr?.message}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
createUrl = `${this.giteaUrl}/api/v1/orgs/${organization}/repos`;
|
|
252
|
+
} else {
|
|
253
|
+
createUrl = `${this.giteaUrl}/api/v1/user/repos`;
|
|
254
|
+
}
|
|
193
255
|
const cr = await axios.post(createUrl,
|
|
194
256
|
{ name: repoName, description, private: isPrivate, auto_init: false },
|
|
195
257
|
{ headers: { Authorization: `token ${this.giteaToken}` }, timeout: 8000 });
|
package/src/tools/git-ignore.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
2
|
import { asToolError, asToolResult, errorToResponse } from "../utils/errors.js";
|
|
3
3
|
import { validateProjectPath } from "../utils/repoHelpers.js";
|
|
4
|
+
import { withRetry } from "../utils/retry.js";
|
|
4
5
|
|
|
5
6
|
const ajv = new Ajv({ allErrors: true });
|
|
6
7
|
|
|
@@ -8,12 +9,12 @@ export function createGitIgnoreTool(git) {
|
|
|
8
9
|
const inputSchema = {
|
|
9
10
|
type: "object",
|
|
10
11
|
properties: {
|
|
11
|
-
projectPath: {
|
|
12
|
+
projectPath: {
|
|
12
13
|
type: "string",
|
|
13
14
|
description: "Caminho absoluto do diretório do projeto"
|
|
14
15
|
},
|
|
15
|
-
action: {
|
|
16
|
-
type: "string",
|
|
16
|
+
action: {
|
|
17
|
+
type: "string",
|
|
17
18
|
enum: ["list", "create", "add", "remove"],
|
|
18
19
|
description: `Ação a executar:
|
|
19
20
|
- list: Lista padrões atuais do .gitignore
|
|
@@ -21,8 +22,8 @@ export function createGitIgnoreTool(git) {
|
|
|
21
22
|
- add: Adiciona padrões ao .gitignore existente
|
|
22
23
|
- remove: Remove padrões do .gitignore`
|
|
23
24
|
},
|
|
24
|
-
patterns: {
|
|
25
|
-
type: "array",
|
|
25
|
+
patterns: {
|
|
26
|
+
type: "array",
|
|
26
27
|
items: { type: "string" },
|
|
27
28
|
description: "Padrões para ignorar. Ex: ['node_modules/', '*.log', '.env', 'dist/', '*.tmp']"
|
|
28
29
|
}
|
|
@@ -66,7 +67,7 @@ EXEMPLOS:
|
|
|
66
67
|
}
|
|
67
68
|
if (action === "create") {
|
|
68
69
|
if (patterns.length === 0) {
|
|
69
|
-
return asToolError("MISSING_PARAMETER", "patterns é obrigatório para criar .gitignore", {
|
|
70
|
+
return asToolError("MISSING_PARAMETER", "patterns é obrigatório para criar .gitignore", {
|
|
70
71
|
parameter: "patterns",
|
|
71
72
|
suggestion: "Forneça um array de padrões. Ex: ['node_modules/', '*.log', '.env']"
|
|
72
73
|
});
|
package/src/tools/git-stash.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
2
|
import { asToolError, asToolResult, errorToResponse } from "../utils/errors.js";
|
|
3
3
|
import { validateProjectPath } from "../utils/repoHelpers.js";
|
|
4
|
+
import { withRetry } from "../utils/retry.js";
|
|
4
5
|
|
|
5
6
|
const ajv = new Ajv({ allErrors: true });
|
|
6
7
|
|
|
@@ -8,12 +9,12 @@ export function createGitStashTool(git) {
|
|
|
8
9
|
const inputSchema = {
|
|
9
10
|
type: "object",
|
|
10
11
|
properties: {
|
|
11
|
-
projectPath: {
|
|
12
|
+
projectPath: {
|
|
12
13
|
type: "string",
|
|
13
14
|
description: "Caminho absoluto do diretório do projeto"
|
|
14
15
|
},
|
|
15
|
-
action: {
|
|
16
|
-
type: "string",
|
|
16
|
+
action: {
|
|
17
|
+
type: "string",
|
|
17
18
|
enum: ["list", "save", "apply", "pop", "drop", "clear"],
|
|
18
19
|
description: `Ação a executar:
|
|
19
20
|
- list: Lista todos os stashes salvos
|
|
@@ -23,15 +24,15 @@ export function createGitStashTool(git) {
|
|
|
23
24
|
- drop: Remove stash específico da lista
|
|
24
25
|
- clear: Remove TODOS os stashes`
|
|
25
26
|
},
|
|
26
|
-
message: {
|
|
27
|
+
message: {
|
|
27
28
|
type: "string",
|
|
28
29
|
description: "Mensagem descritiva para o stash (action='save'). Ex: 'WIP: implementando feature X'"
|
|
29
30
|
},
|
|
30
|
-
ref: {
|
|
31
|
+
ref: {
|
|
31
32
|
type: "string",
|
|
32
33
|
description: "Referência do stash para apply/pop/drop. Ex: 'stash@{0}' (mais recente), 'stash@{1}' (segundo)"
|
|
33
34
|
},
|
|
34
|
-
includeUntracked: {
|
|
35
|
+
includeUntracked: {
|
|
35
36
|
type: "boolean",
|
|
36
37
|
description: "Incluir arquivos não rastreados no stash (action='save'). Default: false"
|
|
37
38
|
}
|
|
@@ -68,7 +69,7 @@ AÇÕES:
|
|
|
68
69
|
validateProjectPath(projectPath);
|
|
69
70
|
if (action === "list") {
|
|
70
71
|
const items = await withRetry(() => git.listStash(projectPath), 3, "stash-list");
|
|
71
|
-
return asToolResult({
|
|
72
|
+
return asToolResult({
|
|
72
73
|
stashes: items.map((s, i) => ({ index: i, ref: `stash@{${i}}`, message: s.message, timestamp: s.timestamp })),
|
|
73
74
|
count: items.length,
|
|
74
75
|
message: items.length === 0 ? "Nenhum stash salvo" : undefined
|