@andrebuzeli/git-mcp 13.6.0 → 14.0.0

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.
@@ -7,16 +7,58 @@ export function createGitStashTool(git) {
7
7
  const inputSchema = {
8
8
  type: "object",
9
9
  properties: {
10
- projectPath: { type: "string" },
11
- action: { type: "string", enum: ["list", "save", "apply", "pop", "drop", "clear"] },
12
- message: { type: "string" },
13
- ref: { type: "string" },
14
- includeUntracked: { type: "boolean" }
10
+ projectPath: {
11
+ type: "string",
12
+ description: "Caminho absoluto do diretório do projeto"
13
+ },
14
+ action: {
15
+ type: "string",
16
+ enum: ["list", "save", "apply", "pop", "drop", "clear"],
17
+ description: `Ação a executar:
18
+ - list: Lista todos os stashes salvos
19
+ - save: Salva mudanças atuais no stash (limpa working directory)
20
+ - apply: Aplica stash sem removê-lo da lista
21
+ - pop: Aplica stash E remove da lista (mais comum)
22
+ - drop: Remove stash específico da lista
23
+ - clear: Remove TODOS os stashes`
24
+ },
25
+ message: {
26
+ type: "string",
27
+ description: "Mensagem descritiva para o stash (action='save'). Ex: 'WIP: implementando feature X'"
28
+ },
29
+ ref: {
30
+ type: "string",
31
+ description: "Referência do stash para apply/pop/drop. Ex: 'stash@{0}' (mais recente), 'stash@{1}' (segundo)"
32
+ },
33
+ includeUntracked: {
34
+ type: "boolean",
35
+ description: "Incluir arquivos não rastreados no stash (action='save'). Default: false"
36
+ }
15
37
  },
16
38
  required: ["projectPath", "action"],
17
- additionalProperties: true
39
+ additionalProperties: false
18
40
  };
19
41
 
42
+ const description = `Gerenciamento de stash Git - salva mudanças temporariamente.
43
+
44
+ QUANDO USAR STASH:
45
+ - Precisa trocar de branch mas tem mudanças não commitadas
46
+ - Quer salvar trabalho em progresso sem commitar
47
+ - Precisa aplicar hotfix urgente em outra branch
48
+
49
+ FLUXO TÍPICO:
50
+ 1. git-stash save message='WIP: minha feature' → salva mudanças
51
+ 2. (trabalha em outra coisa)
52
+ 3. git-stash pop → restaura mudanças
53
+
54
+ AÇÕES:
55
+ - save: Salva e limpa working directory
56
+ - pop: Restaura e remove do stash (use este na maioria dos casos)
57
+ - apply: Restaura mas mantém no stash (para aplicar em múltiplas branches)
58
+ - list: Ver stashes salvos
59
+ - drop: Remover stash específico
60
+ - clear: Remover todos os stashes`;
61
+
20
62
  async function handle(args) {
21
63
  const validate = ajv.compile(inputSchema);
22
64
  if (!validate(args || {})) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
@@ -25,54 +67,52 @@ export function createGitStashTool(git) {
25
67
  if (action === "list") {
26
68
  const items = await git.listStash(projectPath);
27
69
  return asToolResult({
28
- items: items.map((s, i) => ({ index: i, ref: `stash@{${i}}`, message: s.message, timestamp: s.timestamp })),
29
- count: items.length
70
+ stashes: items.map((s, i) => ({ index: i, ref: `stash@{${i}}`, message: s.message, timestamp: s.timestamp })),
71
+ count: items.length,
72
+ message: items.length === 0 ? "Nenhum stash salvo" : undefined
30
73
  });
31
74
  }
32
75
  if (action === "save") {
33
- // Auto-verificação: checar se há mudanças
34
76
  const status = await git.status(projectPath);
35
77
  if (status.isClean && !args.includeUntracked) {
36
78
  return asToolError("NOTHING_TO_STASH", "Working tree limpa, nada para stash", { status });
37
79
  }
38
80
  await git.saveStash(projectPath, args.message || "WIP", !!args.includeUntracked);
39
- return asToolResult({ success: true, message: args.message || "WIP" });
81
+ return asToolResult({ success: true, message: args.message || "WIP", savedFiles: status.modified.length + status.created.length + status.not_added.length });
40
82
  }
41
83
  if (action === "apply") {
42
- // Auto-verificação: checar se stash existe
43
84
  const items = await git.listStash(projectPath);
44
85
  if (items.length === 0) {
45
86
  return asToolError("STASH_NOT_FOUND", "Nenhum stash disponível", { availableStashes: [] });
46
87
  }
47
- await git.applyStash(projectPath, args.ref);
48
- return asToolResult({ success: true, ref: args.ref || "stash@{0}" });
88
+ await git.applyStash(projectPath, args.ref || "stash@{0}");
89
+ return asToolResult({ success: true, ref: args.ref || "stash@{0}", message: "Stash aplicado (ainda está na lista)" });
49
90
  }
50
91
  if (action === "pop") {
51
- // Auto-verificação: checar se stash existe
52
92
  const items = await git.listStash(projectPath);
53
93
  if (items.length === 0) {
54
94
  return asToolError("STASH_NOT_FOUND", "Nenhum stash disponível", { availableStashes: [] });
55
95
  }
56
- await git.popStash(projectPath, args.ref);
57
- return asToolResult({ success: true, ref: args.ref || "stash@{0}" });
96
+ await git.popStash(projectPath, args.ref || "stash@{0}");
97
+ return asToolResult({ success: true, ref: args.ref || "stash@{0}", message: "Stash aplicado e removido da lista" });
58
98
  }
59
99
  if (action === "drop") {
60
100
  const items = await git.listStash(projectPath);
61
101
  if (items.length === 0) {
62
102
  return asToolError("STASH_NOT_FOUND", "Nenhum stash disponível", { availableStashes: [] });
63
103
  }
64
- await git.dropStash(projectPath, args.ref);
65
- return asToolResult({ success: true, ref: args.ref || "stash@{0}" });
104
+ await git.dropStash(projectPath, args.ref || "stash@{0}");
105
+ return asToolResult({ success: true, ref: args.ref || "stash@{0}", message: "Stash removido" });
66
106
  }
67
107
  if (action === "clear") {
68
108
  await git.clearStash(projectPath);
69
109
  return asToolResult({ success: true, message: "Todos os stashes removidos" });
70
110
  }
71
- return asToolError("VALIDATION_ERROR", `Ação não suportada: ${action}`, { availableActions: ["list", "save", "apply", "pop", "drop", "clear"] });
111
+ return asToolError("VALIDATION_ERROR", `Ação '${action}' não suportada`, { availableActions: ["list", "save", "apply", "pop", "drop", "clear"] });
72
112
  } catch (e) {
73
113
  return errorToResponse(e);
74
114
  }
75
115
  }
76
116
 
77
- return { name: "git-stash", description: "Gerencia stash", inputSchema, handle };
117
+ return { name: "git-stash", description, inputSchema, handle };
78
118
  }
@@ -7,15 +7,47 @@ export function createGitSyncTool(git) {
7
7
  const inputSchema = {
8
8
  type: "object",
9
9
  properties: {
10
- projectPath: { type: "string" },
11
- action: { type: "string", enum: ["pull", "fetch"] },
12
- remote: { type: "string" },
13
- branch: { type: "string" }
10
+ projectPath: {
11
+ type: "string",
12
+ description: "Caminho absoluto do diretório do projeto"
13
+ },
14
+ action: {
15
+ type: "string",
16
+ enum: ["pull", "fetch"],
17
+ description: `Ação a executar:
18
+ - fetch: Baixa commits do remote sem aplicar (seguro, apenas atualiza refs remotas)
19
+ - pull: Baixa E aplica commits do remote (pode gerar conflitos)`
20
+ },
21
+ remote: {
22
+ type: "string",
23
+ description: "Nome do remote específico (github, gitea, origin). Se não especificado, tenta todos"
24
+ },
25
+ branch: {
26
+ type: "string",
27
+ description: "Branch para sincronizar. Default: branch atual"
28
+ }
14
29
  },
15
30
  required: ["projectPath", "action"],
16
- additionalProperties: true
31
+ additionalProperties: false
17
32
  };
18
33
 
34
+ const description = `Sincronização com repositórios remotos (GitHub/Gitea).
35
+
36
+ DIFERENÇA FETCH vs PULL:
37
+ - fetch: Seguro - apenas baixa, não modifica working directory
38
+ - pull: Baixa E aplica - pode gerar conflitos se houver mudanças locais
39
+
40
+ QUANDO USAR:
41
+ - fetch: Para ver se há atualizações sem aplicar
42
+ - pull: Para atualizar seu código local com as mudanças do remote
43
+
44
+ FLUXO RECOMENDADO:
45
+ 1. git-workflow status → verificar se tem mudanças locais
46
+ 2. git-sync fetch → baixar atualizações
47
+ 3. git-sync pull → aplicar atualizações (se não tiver conflitos)
48
+
49
+ NOTA: Se pull falhar com conflito, resolva manualmente e faça commit.`;
50
+
19
51
  async function handle(args) {
20
52
  const validate = ajv.compile(inputSchema);
21
53
  if (!validate(args || {})) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
@@ -33,7 +65,7 @@ export function createGitSyncTool(git) {
33
65
  branch,
34
66
  fetched: successful.map(x => x.remote),
35
67
  failed: failed.map(x => ({ remote: x.remote, error: x.error })),
36
- message: successful.length === 0 ? "Nenhum remote alcançado. Verifique conexão e configuração." : undefined
68
+ message: successful.length === 0 ? "Nenhum remote alcançado. Use git-remote ensure para configurar." : `Fetch de ${successful.length} remote(s) concluído`
37
69
  });
38
70
  }
39
71
  if (action === "pull") {
@@ -47,14 +79,14 @@ export function createGitSyncTool(git) {
47
79
  branch,
48
80
  pulled: successful.map(x => x.remote),
49
81
  failed: failed.map(x => ({ remote: x.remote, error: x.error })),
50
- message: successful.length === 0 ? "Nenhum remote alcançado. Verifique conexão e configuração." : undefined
82
+ message: successful.length === 0 ? "Nenhum remote alcançado. Use git-remote ensure para configurar." : `Pull de ${successful.length} remote(s) concluído`
51
83
  });
52
84
  }
53
- return asToolError("VALIDATION_ERROR", `Ação não suportada: ${action}`, { availableActions: ["pull", "fetch"] });
85
+ return asToolError("VALIDATION_ERROR", `Ação '${action}' não suportada`, { availableActions: ["pull", "fetch"] });
54
86
  } catch (e) {
55
87
  return errorToResponse(e);
56
88
  }
57
89
  }
58
90
 
59
- return { name: "git-sync", description: "fetch/pull (opcionalmente múltiplos remotes)", inputSchema, handle };
91
+ return { name: "git-sync", description, inputSchema, handle };
60
92
  }
@@ -7,16 +7,54 @@ export function createGitTagsTool(git) {
7
7
  const inputSchema = {
8
8
  type: "object",
9
9
  properties: {
10
- projectPath: { type: "string" },
11
- action: { type: "string", enum: ["list", "create", "delete", "push"] },
12
- tag: { type: "string" },
13
- ref: { type: "string" },
14
- message: { type: "string" }
10
+ projectPath: {
11
+ type: "string",
12
+ description: "Caminho absoluto do diretório do projeto"
13
+ },
14
+ action: {
15
+ type: "string",
16
+ enum: ["list", "create", "delete", "push"],
17
+ description: `Ação a executar:
18
+ - list: Lista todas as tags existentes
19
+ - create: Cria nova tag no commit atual ou especificado
20
+ - delete: Remove uma tag local
21
+ - push: Envia tag para GitHub e Gitea`
22
+ },
23
+ tag: {
24
+ type: "string",
25
+ description: "Nome da tag. Use versionamento semântico: v1.0.0, v1.1.0, v2.0.0"
26
+ },
27
+ ref: {
28
+ type: "string",
29
+ description: "Commit/branch para criar tag (opcional, default: HEAD)"
30
+ },
31
+ message: {
32
+ type: "string",
33
+ description: "Mensagem da tag anotada (opcional). Se fornecido, cria tag anotada"
34
+ }
15
35
  },
16
36
  required: ["projectPath", "action"],
17
- additionalProperties: true
37
+ additionalProperties: false
18
38
  };
19
39
 
40
+ const description = `Gerenciamento de tags Git para versionamento.
41
+
42
+ AÇÕES DISPONÍVEIS:
43
+ - list: Ver todas as tags existentes
44
+ - create: Criar nova tag de versão
45
+ - delete: Remover tag local
46
+ - push: Enviar tag para GitHub e Gitea
47
+
48
+ VERSIONAMENTO SEMÂNTICO:
49
+ - v1.0.0: Versão inicial
50
+ - v1.1.0: Nova funcionalidade (minor)
51
+ - v1.0.1: Correção de bug (patch)
52
+ - v2.0.0: Breaking change (major)
53
+
54
+ FLUXO TÍPICO:
55
+ 1. git-tags create tag='v1.0.0' message='Release inicial'
56
+ 2. git-tags push tag='v1.0.0'`;
57
+
20
58
  async function handle(args) {
21
59
  const validate = ajv.compile(inputSchema);
22
60
  if (!validate(args || {})) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
@@ -27,38 +65,32 @@ export function createGitTagsTool(git) {
27
65
  return asToolResult({ tags, count: tags.length });
28
66
  }
29
67
  if (action === "create") {
30
- const tag = args.tag;
31
- if (!tag) return asToolError("MISSING_PARAMETER", "tag é obrigatório", { parameter: "tag" });
32
- // Auto-verificação: checar se já existe
68
+ if (!args.tag) return asToolError("MISSING_PARAMETER", "tag é obrigatório", { parameter: "tag" });
33
69
  const existing = await git.listTags(projectPath);
34
- if (existing.includes(tag)) {
35
- return asToolError("TAG_ALREADY_EXISTS", `Tag '${tag}' já existe`, { tag, existingTags: existing });
70
+ if (existing.includes(args.tag)) {
71
+ return asToolError("TAG_ALREADY_EXISTS", `Tag '${args.tag}' já existe`, { tag: args.tag, existingTags: existing });
36
72
  }
37
- await git.createTag(projectPath, tag, args.ref || "HEAD", args.message);
38
- return asToolResult({ success: true, tag, ref: args.ref || "HEAD" });
73
+ await git.createTag(projectPath, args.tag, args.ref || "HEAD", args.message);
74
+ return asToolResult({ success: true, tag: args.tag, ref: args.ref || "HEAD", message: `Tag '${args.tag}' criada. Use action='push' para enviar ao GitHub/Gitea.` });
39
75
  }
40
76
  if (action === "delete") {
41
- const tag = args.tag;
42
- if (!tag) return asToolError("MISSING_PARAMETER", "tag é obrigatório", { parameter: "tag" });
43
- // Auto-verificação: checar se existe
77
+ if (!args.tag) return asToolError("MISSING_PARAMETER", "tag é obrigatório", { parameter: "tag" });
44
78
  const existing = await git.listTags(projectPath);
45
- if (!existing.includes(tag)) {
46
- return asToolError("TAG_NOT_FOUND", `Tag '${tag}' não encontrada`, { tag, existingTags: existing });
79
+ if (!existing.includes(args.tag)) {
80
+ return asToolError("TAG_NOT_FOUND", `Tag '${args.tag}' não encontrada`, { tag: args.tag, existingTags: existing });
47
81
  }
48
- await git.deleteTag(projectPath, tag);
49
- return asToolResult({ success: true, tag });
82
+ await git.deleteTag(projectPath, args.tag);
83
+ return asToolResult({ success: true, tag: args.tag, deleted: true });
50
84
  }
51
85
  if (action === "push") {
52
- const tag = args.tag;
53
- if (!tag) return asToolError("MISSING_PARAMETER", "tag é obrigatório", { parameter: "tag" });
54
- // Auto-verificação: checar se existe
86
+ if (!args.tag) return asToolError("MISSING_PARAMETER", "tag é obrigatório", { parameter: "tag" });
55
87
  const existing = await git.listTags(projectPath);
56
- if (!existing.includes(tag)) {
57
- return asToolError("TAG_NOT_FOUND", `Tag '${tag}' não existe localmente. Crie primeiro com action='create'`, { tag, existingTags: existing });
88
+ if (!existing.includes(args.tag)) {
89
+ return asToolError("TAG_NOT_FOUND", `Tag '${args.tag}' não existe localmente. Crie primeiro com action='create'`, { tag: args.tag, existingTags: existing });
58
90
  }
59
91
  const results = await Promise.allSettled([
60
- git.pushTag(projectPath, "github", tag),
61
- git.pushTag(projectPath, "gitea", tag)
92
+ git.pushTag(projectPath, "github", args.tag),
93
+ git.pushTag(projectPath, "gitea", args.tag)
62
94
  ]);
63
95
  const pushed = [];
64
96
  const failed = [];
@@ -67,13 +99,13 @@ export function createGitTagsTool(git) {
67
99
  if (results[1].status === "fulfilled") pushed.push("gitea");
68
100
  else failed.push({ remote: "gitea", error: results[1].reason?.message });
69
101
 
70
- return asToolResult({ success: pushed.length > 0, tag, pushed, failed });
102
+ return asToolResult({ success: pushed.length > 0, tag: args.tag, pushed, failed });
71
103
  }
72
- return asToolError("VALIDATION_ERROR", `Ação não suportada: ${action}`, { availableActions: ["list", "create", "delete", "push"] });
104
+ return asToolError("VALIDATION_ERROR", `Ação '${action}' não suportada`, { availableActions: ["list", "create", "delete", "push"] });
73
105
  } catch (e) {
74
106
  return errorToResponse(e);
75
107
  }
76
108
  }
77
109
 
78
- return { name: "git-tags", description: "Gerencia tags e push paralelo", inputSchema, handle };
110
+ return { name: "git-tags", description, inputSchema, handle };
79
111
  }
@@ -8,16 +8,56 @@ export function createGitWorkflowTool(pm, git) {
8
8
  const inputSchema = {
9
9
  type: "object",
10
10
  properties: {
11
- projectPath: { type: "string", description: "Caminho absoluto do projeto" },
12
- action: { type: "string", enum: ["init", "status", "add", "remove", "commit", "push", "pull", "sync", "ensure-remotes"], description: "Ação" },
13
- files: { type: "array", items: { type: "string" } },
14
- message: { type: "string" },
15
- force: { type: "boolean", description: "Force push (para resolver divergências de histórico)" }
11
+ projectPath: {
12
+ type: "string",
13
+ description: "Caminho absoluto do diretório do projeto (ex: 'C:/Users/user/projeto' ou '/home/user/projeto')"
14
+ },
15
+ action: {
16
+ type: "string",
17
+ enum: ["init", "status", "add", "remove", "commit", "push", "ensure-remotes"],
18
+ description: `Ação a executar:
19
+ - init: Inicializa repositório git local E cria repos no GitHub/Gitea automaticamente
20
+ - status: Retorna arquivos modificados, staged, untracked (use ANTES de commit para ver o que mudou)
21
+ - add: Adiciona arquivos ao staging (use ANTES de commit)
22
+ - remove: Remove arquivos do staging
23
+ - commit: Cria commit com os arquivos staged (use DEPOIS de add)
24
+ - push: Envia commits para GitHub E Gitea em paralelo (use DEPOIS de commit)
25
+ - ensure-remotes: Configura remotes GitHub e Gitea (use se push falhar por falta de remote)`
26
+ },
27
+ files: {
28
+ type: "array",
29
+ items: { type: "string" },
30
+ description: "Lista de arquivos para add/remove. Use ['.'] para todos os arquivos. Ex: ['src/index.js', 'package.json']"
31
+ },
32
+ message: {
33
+ type: "string",
34
+ description: "Mensagem do commit. Obrigatório para action='commit'. Ex: 'feat: adiciona nova funcionalidade'"
35
+ },
36
+ force: {
37
+ type: "boolean",
38
+ description: "Force push (use apenas se push normal falhar com erro de histórico divergente). Default: false"
39
+ }
16
40
  },
17
41
  required: ["projectPath", "action"],
18
- additionalProperties: true
42
+ additionalProperties: false
19
43
  };
20
44
 
45
+ const description = `Operações Git essenciais com sincronização automática GitHub + Gitea.
46
+
47
+ FLUXO TÍPICO DE TRABALHO:
48
+ 1. git-workflow status → ver arquivos modificados
49
+ 2. git-workflow add → adicionar arquivos ao staging
50
+ 3. git-workflow commit → criar commit
51
+ 4. git-workflow push → enviar para GitHub e Gitea
52
+
53
+ QUANDO USAR CADA ACTION:
54
+ - status: Para verificar estado atual do repositório
55
+ - add: Quando há arquivos modificados para commitar
56
+ - commit: Após add, para salvar as mudanças
57
+ - push: Após commit, para sincronizar com remotes
58
+ - init: Apenas uma vez, para novos projetos
59
+ - ensure-remotes: Se push falhar por falta de configuração`;
60
+
21
61
  async function handle(args) {
22
62
  const validate = ajv.compile(inputSchema);
23
63
  if (!validate(args || {})) {
@@ -29,7 +69,7 @@ export function createGitWorkflowTool(pm, git) {
29
69
  await git.init(projectPath);
30
70
  const repo = getRepoNameFromPath(projectPath);
31
71
  const ensured = await pm.ensureRepos({ repoName: repo, createIfMissing: true });
32
- return asToolResult({ success: true, ensured, message: "Repositório inicializado" });
72
+ return asToolResult({ success: true, ensured, message: "Repositório inicializado localmente e nos providers" });
33
73
  }
34
74
  if (action === "status") {
35
75
  const st = await git.status(projectPath);
@@ -38,7 +78,7 @@ export function createGitWorkflowTool(pm, git) {
38
78
  if (action === "add") {
39
79
  const files = Array.isArray(args.files) && args.files.length ? args.files : ["."];
40
80
  await git.add(projectPath, files);
41
- return asToolResult({ success: true, files });
81
+ return asToolResult({ success: true, files, nextStep: "Use action='commit' com message para criar o commit" });
42
82
  }
43
83
  if (action === "remove") {
44
84
  const files = Array.isArray(args.files) ? args.files : [];
@@ -46,9 +86,11 @@ export function createGitWorkflowTool(pm, git) {
46
86
  return asToolResult({ success: true, files });
47
87
  }
48
88
  if (action === "commit") {
49
- const msg = args.message || "update";
50
- const sha = await git.commit(projectPath, msg);
51
- return asToolResult({ success: true, sha, message: msg });
89
+ if (!args.message) {
90
+ return asToolError("MISSING_PARAMETER", "message é obrigatório para commit", { parameter: "message" });
91
+ }
92
+ const sha = await git.commit(projectPath, args.message);
93
+ return asToolResult({ success: true, sha, message: args.message, nextStep: "Use action='push' para enviar ao GitHub/Gitea" });
52
94
  }
53
95
  if (action === "ensure-remotes") {
54
96
  const repo = getRepoNameFromPath(projectPath);
@@ -59,20 +101,18 @@ export function createGitWorkflowTool(pm, git) {
59
101
  const base = pm.giteaUrl?.replace(/\/$/, "") || "";
60
102
  const giteaUrl = geOwner && base ? `${base}/${geOwner}/${repo}.git` : "";
61
103
  await git.ensureRemotes(projectPath, { githubUrl, giteaUrl });
62
- return asToolResult({ success: true, ensured, remotes: { githubUrl, giteaUrl } });
104
+ const remotes = await git.listRemotes(projectPath);
105
+ return asToolResult({ success: true, ensured, remotes, nextStep: "Agora pode usar action='push'" });
63
106
  }
64
107
  if (action === "push") {
65
108
  const branch = await git.getCurrentBranch(projectPath);
66
109
  const force = !!args.force;
67
- await git.pushParallel(projectPath, branch, force);
68
- return asToolResult({ success: true, branch, remotes: ["github", "gitea"], force });
69
- }
70
- if (action === "sync" || action === "pull") {
71
- // Basic implementation: fetch + status; full merge/pull can be added
72
- return asToolResult({ success: true, message: "Operação de pull/sync não-op realizada" });
110
+ const result = await git.pushParallel(projectPath, branch, force);
111
+ return asToolResult({ success: true, branch, ...result });
73
112
  }
74
- return asToolError("VALIDATION_ERROR", `Ação não suportada: ${action}`, {
75
- availableActions: ["init", "status", "add", "remove", "commit", "push", "pull", "sync", "ensure-remotes"]
113
+ return asToolError("VALIDATION_ERROR", `Ação '${action}' não suportada`, {
114
+ availableActions: ["init", "status", "add", "remove", "commit", "push", "ensure-remotes"],
115
+ suggestion: "Use uma das actions disponíveis"
76
116
  });
77
117
  } catch (e) {
78
118
  return errorToResponse(e);
@@ -81,9 +121,8 @@ export function createGitWorkflowTool(pm, git) {
81
121
 
82
122
  return {
83
123
  name: "git-workflow",
84
- description: "Operações Git locais e remotas em paralelo (GitHub + Gitea)",
124
+ description,
85
125
  inputSchema,
86
126
  handle
87
127
  };
88
128
  }
89
-
@@ -6,6 +6,10 @@ import { MCPError, createError, mapExternalError } from "./errors.js";
6
6
  import { getProvidersEnv } from "./repoHelpers.js";
7
7
  import { withRetry } from "./retry.js";
8
8
 
9
+ // #region agent log
10
+ const debugLog = (loc, msg, data) => { fetch('http://127.0.0.1:8242/ingest/e5799a4a-1a0d-4201-a6ce-42835e6f6fc7',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:loc,message:msg,data,timestamp:Date.now(),sessionId:'debug-session'})}).catch(()=>{}); };
11
+ // #endregion
12
+
9
13
  export class GitAdapter {
10
14
  constructor(providerManager) {
11
15
  this.pm = providerManager;
@@ -16,7 +20,14 @@ export class GitAdapter {
16
20
  }
17
21
 
18
22
  async status(dir) {
23
+ // #region agent log
24
+ const t0 = Date.now();
25
+ debugLog('gitAdapter.js:status', 'START statusMatrix', { dir, hypothesisId: 'A' });
26
+ // #endregion
19
27
  const matrix = await git.statusMatrix({ fs, dir });
28
+ // #region agent log
29
+ debugLog('gitAdapter.js:status', 'END statusMatrix', { duration: Date.now() - t0, fileCount: matrix.length, hypothesisId: 'A' });
30
+ // #endregion
20
31
  const FILE = 0, HEAD = 1, WORKDIR = 2, STAGE = 3;
21
32
  const modified = [], created = [], deleted = [], not_added = [], files = [];
22
33
  for (const row of matrix) {