@andrebuzeli/git-mcp 3.3.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
@@ -1,486 +1,615 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.tagsTool = void 0;
3
+ exports.gitTagsTool = void 0;
4
4
  const zod_1 = require("zod");
5
- const index_js_1 = require("../providers/index.js");
6
- const user_detection_js_1 = require("../utils/user-detection.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");
7
8
  /**
8
- * Tool: tags
9
+ * Tool: git-tags
9
10
  *
10
- * DESCRIÇÃO:
11
- * Gerenciamento completo de tags com suporte multi-provider (GitHub e Gitea)
11
+ * GERENCIAMENTO DE TAGS UNIFICADO
12
+ * Tags inteligentes com versionamento semântico e multi-provider
12
13
  *
13
- * FUNCIONALIDADES:
14
- * - Criação de novas tags
15
- * - Listagem e busca de tags
16
- * - Obtenção de detalhes específicos
17
- * - Exclusão de tags
18
- * - Controle de versão
19
- * - Busca por padrões
20
- *
21
- * USO:
22
- * - Para marcar versões específicas
23
- * - Para controle de release
24
- * - Para rollback de código
25
- * - Para identificação de commits
26
- *
27
- * RECOMENDAÇÕES:
28
- * - Use versionamento semântico
29
- * - Mantenha tags organizadas
30
- * - Documente propósito das tags
31
- * - Use para pontos de referência
32
- */
33
- /**
34
- * Schema de validação para entrada da tool tags
35
- *
36
- * VALIDAÇÕES:
37
- * - action: Ação obrigatória (create, list, get, delete, search)
38
- * - Parâmetros específicos por ação
39
- * - Validação de tipos e formatos
40
- *
41
- * RECOMENDAÇÕES:
42
- * - Sempre valide entrada antes de usar
43
- * - Use parâmetros opcionais adequadamente
44
- * - Documente parâmetros obrigatórios
14
+ * DESIGNED FOR: Programador individual autônomo
15
+ * PHILOSOPHY: Tags organizadas automaticamente para versionamento
45
16
  */
46
- const TagsInputSchema = zod_1.z.object({
47
- action: zod_1.z.enum(['create', 'list', 'get', 'delete', 'search']),
48
- // Parâmetros comuns
49
- provider: zod_1.z.enum(['gitea', 'github']).describe('Provider to use (gitea or github)'),
50
- projectPath: zod_1.z.string().describe('Local project path for git operations'),
51
- repo: zod_1.z.string().optional().describe('Repository name (extracted from projectPath)'),
52
- // Para create
53
- tag_name: zod_1.z.string().optional(),
54
- message: zod_1.z.string().optional(),
55
- target: zod_1.z.string().optional(),
56
- type: zod_1.z.enum(['lightweight', 'annotated']).optional(),
57
- tagger_name: zod_1.z.string().optional(),
58
- tagger_email: zod_1.z.string().optional(),
59
- // Para get/delete
60
- tag: zod_1.z.string().optional(),
61
- // Para list
62
- page: zod_1.z.number().min(1).optional(),
63
- // Para search
64
- query: zod_1.z.string().optional(),
65
- pattern: zod_1.z.string().optional(),
66
- });
17
+ const GitTagsInputSchema = zod_1.z.discriminatedUnion('action', [
18
+ // CREATE TAG - Criação inteligente
19
+ zod_1.z.object({
20
+ action: zod_1.z.literal('create'),
21
+ projectPath: zod_1.z.string(),
22
+ name: zod_1.z.string(),
23
+ message: zod_1.z.string().optional(), // Auto-generate se não fornecido
24
+ target: zod_1.z.string().optional(), // Commit/branch, default HEAD
25
+ type: zod_1.z.enum(['lightweight', 'annotated']).default('annotated'),
26
+ force: zod_1.z.boolean().default(false)
27
+ }),
28
+ // LIST TAGS - Listagem com filtros
29
+ zod_1.z.object({
30
+ action: zod_1.z.literal('list'),
31
+ projectPath: zod_1.z.string(),
32
+ pattern: zod_1.z.string().optional(), // Filtrar por padrão (ex: v*)
33
+ sort: zod_1.z.enum(['version', 'date', 'name']).default('version'),
34
+ limit: zod_1.z.number().default(20)
35
+ }),
36
+ // GET TAG - Detalhes específicos
37
+ zod_1.z.object({
38
+ action: zod_1.z.literal('get'),
39
+ projectPath: zod_1.z.string(),
40
+ name: zod_1.z.string(),
41
+ detailed: zod_1.z.boolean().default(false)
42
+ }),
43
+ // DELETE TAG - Remoção segura
44
+ zod_1.z.object({
45
+ action: zod_1.z.literal('delete'),
46
+ projectPath: zod_1.z.string(),
47
+ name: zod_1.z.string(),
48
+ remote: zod_1.z.boolean().default(true), // Deletar também do remote
49
+ force: zod_1.z.boolean().default(false)
50
+ }),
51
+ // SEARCH TAGS - Busca avançada
52
+ zod_1.z.object({
53
+ action: zod_1.z.literal('search'),
54
+ projectPath: zod_1.z.string(),
55
+ query: zod_1.z.string(),
56
+ pattern: zod_1.z.string().optional(),
57
+ sort: zod_1.z.enum(['relevance', 'date', 'name']).default('relevance'),
58
+ limit: zod_1.z.number().default(10)
59
+ })
60
+ ]);
67
61
  /**
68
- * Schema de saída padronizado
69
- *
70
- * ESTRUTURA:
71
- * - success: Status da operação
72
- * - action: Ação executada
73
- * - message: Mensagem descritiva
74
- * - data: Dados retornados (opcional)
75
- * - error: Detalhes do erro (opcional)
62
+ * Smart Tag Manager
63
+ * Gerencia operações de tags com inteligência
76
64
  */
77
- const TagsResultSchema = zod_1.z.object({
78
- success: zod_1.z.boolean(),
79
- action: zod_1.z.string(),
80
- message: zod_1.z.string(),
81
- data: zod_1.z.any().optional(),
82
- error: zod_1.z.string().optional()
83
- });
84
- /**
85
- * Tool: tags
86
- *
87
- * DESCRIÇÃO:
88
- * Gerenciamento completo de tags Gitea com múltiplas ações
89
- *
90
- * ACTIONS DISPONÍVEIS:
91
- *
92
- * 1. create - Criar nova tag
93
- * Parâmetros:
94
- * - owner (obrigatório): Proprietário do repositório
95
- * - repo (obrigatório): Nome do repositório
96
- * - tag_name (obrigatório): Nome da tag
97
- * - message (opcional): Mensagem da tag (para tags anotadas)
98
- * - target (obrigatório): Commit, branch ou tag alvo
99
- * - type (opcional): Tipo de tag (lightweight, annotated) - padrão: lightweight
100
- * - tagger_name (opcional): Nome do tagger (para tags anotadas)
101
- * - tagger_email (opcional): Email do tagger (para tags anotadas)
102
- *
103
- * 2. list - Listar tags
104
- * Parâmetros:
105
- * - owner (obrigatório): Proprietário do repositório
106
- * - repo (obrigatório): Nome do repositório
107
- * - page (opcional): Página da listagem (padrão: 1)
108
- * - limit (opcional): Itens por página (padrão: 30, máximo: 100)
109
- *
110
- * 3. get - Obter detalhes da tag
111
- * Parâmetros:
112
- * - owner (obrigatório): Proprietário do repositório
113
- * - repo (obrigatório): Nome do repositório
114
- * - tag (obrigatório): Nome da tag
115
- *
116
- * 4. delete - Deletar tag
117
- * Parâmetros:
118
- * - owner (obrigatório): Proprietário do repositório
119
- * - repo (obrigatório): Nome do repositório
120
- * - tag (obrigatório): Nome da tag
121
- *
122
- * 5. search - Buscar tags
123
- * Parâmetros:
124
- * - owner (obrigatório): Proprietário do repositório
125
- * - repo (obrigatório): Nome do repositório
126
- * - query (opcional): Termo de busca
127
- * - pattern (opcional): Padrão de busca (ex: v*.*.*)
128
- *
129
- * RECOMENDAÇÕES DE USO:
130
- * - Use convenções de nomenclatura consistentes
131
- * - Documente propósito das tags
132
- * - Mantenha tags organizadas
133
- * - Use versionamento semântico
134
- * - Use tags anotadas para releases importantes
135
- * - Limpe tags antigas regularmente
136
- */
137
- exports.tagsTool = {
138
- name: 'git-tags',
139
- description: 'tool: Gerencia tags Git para versionamento e releases\n──────────────\naction create: cria nova tag\naction create requires: repo, tag_name, message, target, type, tagger_name, tagger_email, provider\n───────────────\naction list: lista tags do repositório\naction list requires: repo, page,provider\n───────────────\naction get: obtém detalhes de tag\naction get requires: repo, tag, provider\n───────────────\naction delete: remove tag\naction delete requires: repo, tag, provider\n───────────────\naction search: busca tags por critérios\naction search requires: repo, query, pattern, provider',
140
- inputSchema: {
141
- type: 'object',
142
- properties: {
143
- action: {
144
- type: 'string',
145
- enum: ['create', 'list', 'get', 'delete', 'search'],
146
- description: 'Action to perform on tags'
147
- },
148
- repo: { type: 'string', description: 'Repository name' },
149
- provider: { type: 'string', description: 'Provider to use (github, gitea, or omit for default)' },
150
- tag_name: { type: 'string', description: 'Tag name' },
151
- message: { type: 'string', description: 'Tag message (for annotated tags)' },
152
- target: { type: 'string', description: 'Target commit SHA, branch or tag' },
153
- type: { type: 'string', enum: ['lightweight', 'annotated'], description: 'Tag type' },
154
- tagger_name: { type: 'string', description: 'Tagger name' },
155
- tagger_email: { type: 'string', description: 'Tagger email' },
156
- tag: { type: 'string', description: 'Tag name for get/delete operations' },
157
- page: { type: 'number', description: 'Page number', minimum: 1 },
158
- query: { type: 'string', description: 'Search query' },
159
- pattern: { type: 'string', description: 'Search pattern (e.g., v*.*.*)' }
160
- },
161
- required: ['action', 'provider', 'projectPath']
162
- },
163
- /**
164
- * Handler principal da tool tags
165
- *
166
- * FUNCIONALIDADE:
167
- * - Valida entrada usando Zod schema
168
- * - Roteia para método específico baseado na ação
169
- * - Trata erros de forma uniforme
170
- * - Retorna resultado padronizado
171
- *
172
- * FLUXO:
173
- * 1. Validação de entrada
174
- * 2. Seleção do provider
175
- * 3. Roteamento por ação
176
- * 4. Execução do método específico
177
- * 5. Tratamento de erros
178
- * 6. Retorno de resultado
179
- *
180
- * TRATAMENTO DE ERROS:
181
- * - Validação: erro de schema
182
- * - Execução: erro da operação
183
- * - Roteamento: ação não suportada
184
- *
185
- * RECOMENDAÇÕES:
186
- * - Sempre valide entrada antes de processar
187
- * - Trate erros específicos adequadamente
188
- * - Log detalhes de erro para debug
189
- * - Retorne mensagens de erro úteis
190
- */
191
- async handler(input) {
65
+ class SmartTagManager {
66
+ static async getAllTags(projectPath) {
67
+ const gitOps = new git_operations_js_1.GitOperations(projectPath);
192
68
  try {
193
- const validatedInput = TagsInputSchema.parse(input);
194
- // Aplicar extração automática do nome do repositório
195
- const processedInput = (0, user_detection_js_1.applyAutoRepoExtraction)(validatedInput);
196
- // Aplicar auto-detecção apenas para owner dentro do provider especificado
197
- const finalInput = await (0, user_detection_js_1.applyAutoUserDetection)(processedInput, processedInput.provider);
198
- // Usar o provider especificado pelo usuário (obrigatório)
199
- if (!processedInput.provider) {
200
- throw new Error("Parâmetro 'provider' é obrigatório e não pode ser omitido");
201
- }
202
- const provider = index_js_1.globalProviderFactory.getProvider(processedInput.provider);
203
- if (!provider) {
204
- throw new Error(`Provider '${processedInput.provider}' não encontrado`);
205
- }
206
- switch (processedInput.action) {
207
- case 'create':
208
- return await this.createTag(processedInput, provider);
209
- case 'list':
210
- return await this.listTags(processedInput, provider);
211
- case 'get':
212
- return await this.getTag(processedInput, provider);
213
- case 'delete':
214
- return await this.deleteTag(processedInput, provider);
215
- case 'search':
216
- return await this.searchTags(processedInput, provider);
217
- default:
218
- throw new Error(`Ação não suportada: ${processedInput.action}`);
69
+ // Get all tags with details
70
+ const tagResult = await gitOps.runCommand('git', ['tag', '-l', '--format=%(refname:short)|%(objectname)|%(creatordate)|%(subject)']);
71
+ if (!tagResult.success) {
72
+ return [];
219
73
  }
74
+ const lines = tagResult.output.trim().split('\n');
75
+ const tags = [];
76
+ lines.forEach(line => {
77
+ const parts = line.split('|');
78
+ if (parts.length >= 4) {
79
+ const [name, hash, date, message] = parts;
80
+ tags.push({
81
+ name,
82
+ hash,
83
+ date: new Date(date),
84
+ message: message.trim(),
85
+ type: this.detectTagType(name),
86
+ version: this.parseVersion(name)
87
+ });
88
+ }
89
+ });
90
+ return tags;
220
91
  }
221
92
  catch (error) {
93
+ return [];
94
+ }
95
+ }
96
+ static async getTagInfo(projectPath, tagName) {
97
+ const gitOps = new git_operations_js_1.GitOperations(projectPath);
98
+ try {
99
+ // Check if tag exists
100
+ const existsResult = await gitOps.runCommand('git', ['tag', '-l', tagName]);
101
+ const exists = existsResult.success && existsResult.output.trim() === tagName;
102
+ if (!exists) {
103
+ return { name: tagName, exists: false };
104
+ }
105
+ // Get detailed info
106
+ const showResult = await gitOps.runCommand('git', ['show', '--quiet', '--format=fuller', tagName]);
107
+ const info = this.parseTagShow(showResult.success ? showResult.output : '');
222
108
  return {
223
- success: false,
224
- action: input.action,
225
- message: 'Erro na operação de tags',
226
- error: error instanceof Error ? error.message : String(error)
109
+ name: tagName,
110
+ exists: true,
111
+ ...info,
112
+ type: this.detectTagType(tagName),
113
+ version: this.parseVersion(tagName)
227
114
  };
228
115
  }
229
- },
116
+ catch (error) {
117
+ return { name: tagName, exists: false, error: error instanceof Error ? error.message : String(error) };
118
+ }
119
+ }
120
+ static parseTagShow(output) {
121
+ const lines = output.split('\n');
122
+ let info = {
123
+ hash: '',
124
+ author: '',
125
+ date: null,
126
+ message: ''
127
+ };
128
+ let inMessage = false;
129
+ let messageLines = [];
130
+ lines.forEach(line => {
131
+ if (line.startsWith('commit ')) {
132
+ info.hash = line.substring(7);
133
+ }
134
+ else if (line.startsWith('Tagger:')) {
135
+ info.author = line.substring(7).trim();
136
+ }
137
+ else if (line.startsWith('Date:')) {
138
+ info.date = new Date(line.substring(5).trim());
139
+ }
140
+ else if (line.startsWith('Tag:')) {
141
+ // Lightweight tag
142
+ info.lightweight = true;
143
+ }
144
+ else if (inMessage || (!line.trim() && messageLines.length > 0)) {
145
+ inMessage = true;
146
+ messageLines.push(line);
147
+ }
148
+ });
149
+ info.message = messageLines.join('\n').trim();
150
+ return info;
151
+ }
152
+ static detectTagType(tagName) {
153
+ // Check for semantic versioning
154
+ if (/^v?\d+\.\d+\.\d+/.test(tagName)) {
155
+ return 'semantic';
156
+ }
157
+ // For now, we can't easily distinguish annotated vs lightweight without more git commands
158
+ // This would require checking if the tag points to a tag object or directly to a commit
159
+ return 'other';
160
+ }
161
+ static parseVersion(tagName) {
162
+ const match = tagName.match(/^v?(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
163
+ if (!match)
164
+ return null;
165
+ return {
166
+ major: parseInt(match[1]),
167
+ minor: parseInt(match[2]),
168
+ patch: parseInt(match[3]),
169
+ prerelease: match[4]
170
+ };
171
+ }
172
+ static generateTagMessage(tagName, customMessage) {
173
+ if (customMessage)
174
+ return customMessage;
175
+ const version = this.parseVersion(tagName);
176
+ if (version) {
177
+ return `Release ${tagName}`;
178
+ }
179
+ return `Tag: ${tagName}`;
180
+ }
181
+ static validateTagName(name) {
182
+ // Git tag name rules
183
+ if (!name || name.trim().length === 0) {
184
+ return { valid: false, error: 'Tag name cannot be empty' };
185
+ }
186
+ if (name.includes(' ')) {
187
+ return { valid: false, error: 'Tag name cannot contain spaces' };
188
+ }
189
+ if (name.startsWith('-') || name.endsWith('-')) {
190
+ return { valid: false, error: 'Tag name cannot start or end with dash' };
191
+ }
192
+ // Check for invalid characters
193
+ if (/[^a-zA-Z0-9._-]/g.test(name)) {
194
+ return { valid: false, error: 'Tag name contains invalid characters' };
195
+ }
196
+ return { valid: true };
197
+ }
198
+ static sortTags(tags, sortBy) {
199
+ return tags.sort((a, b) => {
200
+ switch (sortBy) {
201
+ case 'version':
202
+ const aVer = a.version;
203
+ const bVer = b.version;
204
+ if (!aVer && !bVer)
205
+ return a.name.localeCompare(b.name);
206
+ if (!aVer)
207
+ return 1;
208
+ if (!bVer)
209
+ return -1;
210
+ if (aVer.major !== bVer.major)
211
+ return bVer.major - aVer.major;
212
+ if (aVer.minor !== bVer.minor)
213
+ return bVer.minor - aVer.minor;
214
+ return bVer.patch - aVer.patch;
215
+ case 'date':
216
+ return b.date.getTime() - a.date.getTime();
217
+ case 'name':
218
+ default:
219
+ return a.name.localeCompare(b.name);
220
+ }
221
+ });
222
+ }
223
+ static filterTags(tags, pattern) {
224
+ if (!pattern)
225
+ return tags;
226
+ const regex = new RegExp(pattern.replace(/\*/g, '.*'), 'i');
227
+ return tags.filter(tag => regex.test(tag.name));
228
+ }
229
+ }
230
+ /**
231
+ * Classe principal para executar operações Git tags
232
+ */
233
+ class GitTagsExecutor {
234
+ errorHandler = new error_handler_js_1.UniversalErrorHandler();
230
235
  /**
231
- * Cria uma nova tag no repositório
232
- *
233
- * FUNCIONALIDADE:
234
- * - Cria tag com nome e target especificados
235
- * - Suporta tags lightweight e anotadas
236
- * - Permite configuração de tagger
237
- *
238
- * PARÂMETROS OBRIGATÓRIOS:
239
- * - owner: Proprietário do repositório
240
- * - repo: Nome do repositório
241
- * - tag_name: Nome da tag
242
- * - target: Commit, branch ou tag alvo
243
- *
244
- * PARÂMETROS OPCIONAIS:
245
- * - message: Mensagem da tag (para tags anotadas)
246
- * - type: Tipo de tag (lightweight, annotated) - padrão: lightweight
247
- * - tagger_name: Nome do tagger (para tags anotadas)
248
- * - tagger_email: Email do tagger (para tags anotadas)
249
- *
250
- * VALIDAÇÕES:
251
- * - Todos os parâmetros obrigatórios
252
- * - Nome da tag deve ser único no repositório
253
- * - Target deve existir
254
- * - Usuário deve ter permissão de escrita
255
- *
256
- * RECOMENDAÇÕES:
257
- * - Use convenções de nomenclatura consistentes
258
- * - Use tags anotadas para releases importantes
259
- * - Documente propósito da tag
260
- * - Use versionamento semântico
236
+ * Executa operação create
261
237
  */
262
- async createTag(params, provider) {
238
+ async executeCreate(detection, input) {
263
239
  try {
264
- if (!params.repo || !params.tag_name || !params.target) {
265
- throw new Error('Repo, tag_name e target são obrigatórios');
240
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
241
+ // Validate tag name
242
+ const nameValidation = SmartTagManager.validateTagName(input.name);
243
+ if (!nameValidation.valid) {
244
+ throw new Error(`Invalid tag name: ${nameValidation.error}`);
266
245
  }
267
- const currentUser = await provider.getCurrentUser();
268
- const owner = currentUser.login;
269
- const tagData = {
270
- tag_name: params.tag_name,
271
- target: params.target
272
- };
273
- if (params.type === 'annotated') {
274
- if (params.message)
275
- tagData.message = params.message;
276
- if (params.tagger_name)
277
- tagData.tagger_name = params.tagger_name;
278
- if (params.tagger_email)
279
- tagData.tagger_email = params.tagger_email;
246
+ // Check if tag already exists
247
+ const existingTag = await SmartTagManager.getTagInfo(detection.projectPath, input.name);
248
+ if (existingTag.exists && !input.force) {
249
+ throw new Error(`Tag '${input.name}' already exists. Use force=true to overwrite.`);
280
250
  }
281
- const tag = await provider.createTag(owner, params.repo, tagData);
282
- return {
251
+ // Determine target
252
+ const target = input.target || 'HEAD';
253
+ // Validate target exists
254
+ const targetResult = await gitOps.runCommand('git', ['rev-parse', '--verify', target]);
255
+ if (!targetResult.success) {
256
+ throw new Error(`Invalid target reference: ${target}`);
257
+ }
258
+ // Generate message if not provided
259
+ const message = SmartTagManager.generateTagMessage(input.name, input.message);
260
+ // Create tag
261
+ const tagArgs = input.type === 'annotated' ?
262
+ ['tag', '-a', input.name, '-m', message, target] :
263
+ ['tag', input.name, target];
264
+ if (input.force) {
265
+ tagArgs.splice(1, 0, '-f');
266
+ }
267
+ const tagResult = await gitOps.runCommand('git', tagArgs);
268
+ if (!tagResult.success) {
269
+ throw new Error(`Failed to create tag: ${tagResult.error}`);
270
+ }
271
+ // Push tag to all providers
272
+ for (const provider of detection.providers) {
273
+ try {
274
+ await gitOps.runCommand('git', ['push', provider, input.name]);
275
+ }
276
+ catch (error) {
277
+ console.warn(`Failed to push tag to ${provider}:`, error);
278
+ }
279
+ }
280
+ return (0, auto_detection_js_1.createUniversalResponse)({
283
281
  success: true,
284
282
  action: 'create',
285
- message: `Tag '${params.tag_name}' criada com sucesso`,
286
- data: tag
287
- };
283
+ message: `Tag '${input.name}' created successfully`,
284
+ data: {
285
+ tag: input.name,
286
+ message: message,
287
+ target: target,
288
+ type: input.type,
289
+ force: input.force,
290
+ pushed: detection.providers,
291
+ tagType: SmartTagManager.detectTagType(input.name)
292
+ },
293
+ autoDetected: {
294
+ repo: detection.repoName,
295
+ owner: detection.owner,
296
+ providers: detection.providers
297
+ }
298
+ });
288
299
  }
289
300
  catch (error) {
290
- throw new Error(`Falha ao criar tag: ${error instanceof Error ? error.message : String(error)}`);
301
+ return this.errorHandler.toUniversalResponse();
291
302
  }
292
- },
303
+ }
293
304
  /**
294
- * Lista tags do repositório
295
- *
296
- * FUNCIONALIDADE:
297
- * - Lista tags com paginação
298
- * - Retorna informações básicas de cada tag
299
- * - Inclui commit alvo e URLs de download
300
- *
301
- * PARÂMETROS OBRIGATÓRIOS:
302
- * - owner: Proprietário do repositório
303
- * - repo: Nome do repositório
304
- *
305
- * PARÂMETROS OPCIONAIS:
306
- * - page: Página da listagem (padrão: 1)
307
- * - limit: Itens por página (padrão: 30, máximo: 100)
308
- *
309
- * VALIDAÇÕES:
310
- * - e repo obrigatórios
311
- * - Page deve ser >= 1
312
- * - Limit deve ser entre 1 e 100
313
- *
314
- * RECOMENDAÇÕES:
315
- * - Use paginação para repositórios com muitas tags
316
- * - Monitore número total de tags
317
- * - Verifique commit alvo de cada tag
318
- * - Mantenha tags organizadas
305
+ * Executa operação list
319
306
  */
320
- async listTags(params, provider) {
307
+ async executeList(detection, input) {
321
308
  try {
322
- if (!params.repo) {
323
- throw new Error('Repo é obrigatório');
324
- }
325
- const currentUser = await provider.getCurrentUser();
326
- const owner = currentUser.login;
327
- const page = params.page || 1;
328
- const tags = await provider.listTags((await provider.getCurrentUser()).login, params.repo, page);
329
- return {
309
+ const allTags = await SmartTagManager.getAllTags(detection.projectPath);
310
+ const filteredTags = SmartTagManager.filterTags(allTags, input.pattern);
311
+ const sortedTags = SmartTagManager.sortTags(filteredTags, input.sort);
312
+ const limitedTags = sortedTags.slice(0, input.limit);
313
+ return (0, auto_detection_js_1.createUniversalResponse)({
330
314
  success: true,
331
315
  action: 'list',
332
- message: `${tags.length} tags encontradas`,
316
+ message: `Found ${limitedTags.length} tags`,
333
317
  data: {
334
- tags,
335
- page,
336
- total: tags.length
318
+ tags: limitedTags,
319
+ total: allTags.length,
320
+ filtered: filteredTags.length,
321
+ pattern: input.pattern,
322
+ sort: input.sort,
323
+ limit: input.limit
324
+ },
325
+ autoDetected: {
326
+ repo: detection.repoName,
327
+ owner: detection.owner,
328
+ providers: detection.providers
337
329
  }
338
- };
330
+ });
339
331
  }
340
332
  catch (error) {
341
- throw new Error(`Falha ao listar tags: ${error instanceof Error ? error.message : String(error)}`);
333
+ return this.errorHandler.toUniversalResponse();
342
334
  }
343
- },
335
+ }
344
336
  /**
345
- * Obtém detalhes de uma tag específica
346
- *
347
- * FUNCIONALIDADE:
348
- * - Retorna informações completas da tag
349
- * - Inclui nome, commit alvo e URLs
350
- * - Mostra tipo da tag (lightweight/anotada)
351
- *
352
- * PARÂMETROS OBRIGATÓRIOS:
353
- * - owner: Proprietário do repositório
354
- * - repo: Nome do repositório
355
- * - tag: Nome da tag
356
- *
357
- * VALIDAÇÕES:
358
- * - Todos os parâmetros obrigatórios
359
- * - Tag deve existir no repositório
360
- * - Nome deve ser válido
361
- *
362
- * RECOMENDAÇÕES:
363
- * - Use para obter detalhes completos
364
- * - Verifique commit alvo da tag
365
- * - Analise URLs de download
366
- * - Monitore mudanças importantes
337
+ * Executa operação get
367
338
  */
368
- async getTag(params, provider) {
339
+ async executeGet(detection, input) {
369
340
  try {
370
- if (!params.repo || !params.tag) {
371
- throw new Error('Repo e tag são obrigatórios');
341
+ const tagInfo = await SmartTagManager.getTagInfo(detection.projectPath, input.name);
342
+ if (!tagInfo.exists) {
343
+ return (0, auto_detection_js_1.createUniversalResponse)({
344
+ success: false,
345
+ action: 'get',
346
+ message: `Tag '${input.name}' not found`,
347
+ error: {
348
+ code: 'TAG_NOT_FOUND',
349
+ message: `Tag '${input.name}' does not exist`,
350
+ cause: 'Tag not found in repository',
351
+ suggestion: 'Check tag name or create it first'
352
+ },
353
+ autoDetected: {
354
+ repo: detection.repoName,
355
+ owner: detection.owner,
356
+ providers: detection.providers
357
+ }
358
+ });
372
359
  }
373
- const currentUser = await provider.getCurrentUser();
374
- const owner = currentUser.login;
375
- // Implementar obtenção de tag específica
376
- // Por enquanto, retorna mensagem de funcionalidade
377
- return {
360
+ return (0, auto_detection_js_1.createUniversalResponse)({
378
361
  success: true,
379
362
  action: 'get',
380
- message: `Tag '${params.tag}' obtida com sucesso`,
363
+ message: `Tag '${input.name}' details`,
381
364
  data: {
382
- tag: params.tag,
383
- note: 'Funcionalidade de obtenção de tag específica será implementada'
365
+ tag: tagInfo,
366
+ detailed: input.detailed
367
+ },
368
+ autoDetected: {
369
+ repo: detection.repoName,
370
+ owner: detection.owner,
371
+ providers: detection.providers
384
372
  }
385
- };
373
+ });
386
374
  }
387
375
  catch (error) {
388
- throw new Error(`Falha ao obter tag: ${error instanceof Error ? error.message : String(error)}`);
376
+ return this.errorHandler.toUniversalResponse();
389
377
  }
390
- },
378
+ }
391
379
  /**
392
- * Deleta uma tag do repositório
393
- *
394
- * FUNCIONALIDADE:
395
- * - Remove tag especificada
396
- * - Mantém commit alvo intacto
397
- * - Confirma exclusão bem-sucedida
398
- *
399
- * PARÂMETROS OBRIGATÓRIOS:
400
- * - owner: Proprietário do repositório
401
- * - repo: Nome do repositório
402
- * - tag: Nome da tag
403
- *
404
- * VALIDAÇÕES:
405
- * - Todos os parâmetros obrigatórios
406
- * - Tag deve existir
407
- * - Usuário deve ter permissão de exclusão
408
- *
409
- * RECOMENDAÇÕES:
410
- * - Confirme exclusão antes de executar
411
- * - Verifique se tag não está sendo usada
412
- * - Mantenha backup se necessário
413
- * - Documente motivo da exclusão
380
+ * Executa operação delete
414
381
  */
415
- async deleteTag(params, provider) {
382
+ async executeDelete(detection, input) {
416
383
  try {
417
- if (!params.repo || !params.tag) {
418
- throw new Error('Repo e tag são obrigatórios');
384
+ const gitOps = new git_operations_js_1.GitOperations(detection.projectPath);
385
+ // Check if tag exists
386
+ const tagInfo = await SmartTagManager.getTagInfo(detection.projectPath, input.name);
387
+ if (!tagInfo.exists && !input.force) {
388
+ throw new Error(`Tag '${input.name}' does not exist`);
419
389
  }
420
- const currentUser = await provider.getCurrentUser();
421
- const owner = currentUser.login;
422
- await provider.deleteTag((await provider.getCurrentUser()).login, params.repo, params.tag);
423
- return {
390
+ // Delete local tag
391
+ const deleteArgs = input.force ? ['tag', '-d', input.name] : ['tag', '-d', input.name];
392
+ const deleteResult = await gitOps.runCommand('git', deleteArgs);
393
+ if (!deleteResult.success && !input.force) {
394
+ throw new Error(`Failed to delete tag: ${deleteResult.error}`);
395
+ }
396
+ // Delete from remotes if requested
397
+ const remoteResults = [];
398
+ if (input.remote) {
399
+ for (const provider of detection.providers) {
400
+ try {
401
+ const remoteDeleteResult = await gitOps.runCommand('git', ['push', provider, `:${input.name}`]);
402
+ remoteResults.push({
403
+ provider,
404
+ success: remoteDeleteResult.success,
405
+ error: remoteDeleteResult.error
406
+ });
407
+ }
408
+ catch (error) {
409
+ remoteResults.push({
410
+ provider,
411
+ success: false,
412
+ error: error instanceof Error ? error.message : String(error)
413
+ });
414
+ }
415
+ }
416
+ }
417
+ return (0, auto_detection_js_1.createUniversalResponse)({
424
418
  success: true,
425
419
  action: 'delete',
426
- message: `Tag '${params.tag}' deletada com sucesso`,
427
- data: { deleted: true }
428
- };
420
+ message: `Tag '${input.name}' deleted successfully`,
421
+ data: {
422
+ tag: input.name,
423
+ force: input.force,
424
+ remote: input.remote,
425
+ remoteResults: remoteResults,
426
+ existed: tagInfo.exists
427
+ },
428
+ autoDetected: {
429
+ repo: detection.repoName,
430
+ owner: detection.owner,
431
+ providers: detection.providers
432
+ }
433
+ });
429
434
  }
430
435
  catch (error) {
431
- throw new Error(`Falha ao deletar tag: ${error instanceof Error ? error.message : String(error)}`);
436
+ return this.errorHandler.toUniversalResponse();
432
437
  }
433
- },
438
+ }
434
439
  /**
435
- * Busca tags por critérios específicos
436
- *
437
- * FUNCIONALIDADE:
438
- * - Busca tags por nome ou padrão
439
- * - Suporta padrões glob (ex: v*.*.*)
440
- * - Retorna resultados relevantes
441
- *
442
- * PARÂMETROS OBRIGATÓRIOS:
443
- * - owner: Proprietário do repositório
444
- * - repo: Nome do repositório
445
- *
446
- * PARÂMETROS OPCIONAIS:
447
- * - query: Termo de busca
448
- * - pattern: Padrão de busca (ex: v*.*.*)
449
- *
450
- * VALIDAÇÕES:
451
- * - e repo obrigatórios
452
- * - Query ou pattern deve ser fornecido
453
- * - Repositório deve existir
454
- *
455
- * RECOMENDAÇÕES:
456
- * - Use padrões glob para busca eficiente
457
- * - Combine com filtros de nome
458
- * - Analise resultados para relevância
459
- * - Use para encontrar tags relacionadas
440
+ * Executa operação search
460
441
  */
461
- async searchTags(params, provider) {
442
+ async executeSearch(detection, input) {
462
443
  try {
463
- if (!params.repo) {
464
- throw new Error('Repo é obrigatório');
444
+ const allTags = await SmartTagManager.getAllTags(detection.projectPath);
445
+ // Search by query
446
+ let matchedTags = allTags.filter(tag => tag.name.toLowerCase().includes(input.query.toLowerCase()) ||
447
+ tag.message.toLowerCase().includes(input.query.toLowerCase()));
448
+ // Apply pattern filter if provided
449
+ if (input.pattern) {
450
+ matchedTags = SmartTagManager.filterTags(matchedTags, input.pattern);
465
451
  }
466
- if (!params.query && !params.pattern) {
467
- throw new Error('Query ou pattern deve ser fornecido');
452
+ // Sort results
453
+ let sortedTags;
454
+ switch (input.sort) {
455
+ case 'date':
456
+ sortedTags = SmartTagManager.sortTags(matchedTags, 'date');
457
+ break;
458
+ case 'name':
459
+ sortedTags = SmartTagManager.sortTags(matchedTags, 'name');
460
+ break;
461
+ case 'relevance':
462
+ default:
463
+ // For relevance, keep current order (already filtered by query)
464
+ sortedTags = matchedTags;
465
+ break;
468
466
  }
469
- // Implementar busca de tags
470
- // Por enquanto, retorna mensagem de funcionalidade
471
- return {
467
+ const limitedTags = sortedTags.slice(0, input.limit);
468
+ return (0, auto_detection_js_1.createUniversalResponse)({
472
469
  success: true,
473
470
  action: 'search',
474
- message: `Busca por tags solicitada`,
471
+ message: `Found ${limitedTags.length} tags matching '${input.query}'`,
475
472
  data: {
476
- query: params.query || 'não fornecido',
477
- pattern: params.pattern || 'não fornecido',
478
- results: 'Funcionalidade de busca será implementada'
473
+ query: input.query,
474
+ results: limitedTags,
475
+ total: allTags.length,
476
+ matched: matchedTags.length,
477
+ pattern: input.pattern,
478
+ sort: input.sort,
479
+ limit: input.limit
480
+ },
481
+ autoDetected: {
482
+ repo: detection.repoName,
483
+ owner: detection.owner,
484
+ providers: detection.providers
479
485
  }
480
- };
486
+ });
487
+ }
488
+ catch (error) {
489
+ return this.errorHandler.toUniversalResponse();
490
+ }
491
+ }
492
+ }
493
+ /**
494
+ * Tool principal git-tags
495
+ */
496
+ exports.gitTagsTool = {
497
+ name: 'git-tags',
498
+ description: `🏷️ GERENCIAMENTO DE TAGS UNIFICADO
499
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
500
+ 🎯 TAGS INTELIGENTES:
501
+ • create: Criação com auto-detecção de tipo
502
+ • list: Listagem com filtros e ordenação
503
+ • get: Detalhes completos de tags
504
+ • delete: Remoção local e remota
505
+ • search: Busca avançada por nome/mensagem
506
+
507
+ 🔍 VERSIONAMENTO SEMÂNTICO:
508
+ • Detecção automática de tags semânticas
509
+ • Suporte a versionamento (major.minor.patch)
510
+ • Validação de nomes de tags
511
+ • Ordenação por versão
512
+
513
+ ⚡ OPERAÇÕES MULTI-PROVIDER:
514
+ • Push automático para todos os providers
515
+ • Delete remoto opcional
516
+ • Sincronização automática
517
+ • Validação de consistência
518
+
519
+ 🤖 COMPATÍVEL COM AI AGENTS:
520
+ • Interface universal para qualquer IDE
521
+ • Auto-detecção completa de contexto
522
+ • Respostas estruturadas consistentes
523
+ • Error handling inteligente
524
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
525
+ inputSchema: {
526
+ type: 'object',
527
+ properties: {
528
+ action: {
529
+ type: 'string',
530
+ enum: ['create', 'list', 'get', 'delete', 'search'],
531
+ description: 'Ação do sistema de tags'
532
+ },
533
+ projectPath: {
534
+ type: 'string',
535
+ description: 'Caminho absoluto do projeto'
536
+ },
537
+ name: {
538
+ type: 'string',
539
+ description: 'Nome da tag'
540
+ },
541
+ message: {
542
+ type: 'string',
543
+ description: 'Mensagem da tag (para annotated)'
544
+ },
545
+ target: {
546
+ type: 'string',
547
+ description: 'Target da tag (commit/branch)'
548
+ },
549
+ type: {
550
+ type: 'string',
551
+ enum: ['lightweight', 'annotated'],
552
+ description: 'Tipo da tag'
553
+ },
554
+ force: {
555
+ type: 'boolean',
556
+ description: 'Forçar operação'
557
+ },
558
+ pattern: {
559
+ type: 'string',
560
+ description: 'Padrão para filtrar tags'
561
+ },
562
+ sort: {
563
+ type: 'string',
564
+ enum: ['version', 'date', 'name', 'relevance'],
565
+ description: 'Critério de ordenação'
566
+ },
567
+ limit: {
568
+ type: 'number',
569
+ description: 'Limite de resultados'
570
+ },
571
+ detailed: {
572
+ type: 'boolean',
573
+ description: 'Informações detalhadas'
574
+ },
575
+ remote: {
576
+ type: 'boolean',
577
+ description: 'Operação também no remote'
578
+ },
579
+ query: {
580
+ type: 'string',
581
+ description: 'Termo de busca'
582
+ }
583
+ },
584
+ required: ['action', 'projectPath']
585
+ },
586
+ async handler(input) {
587
+ const executor = new GitTagsExecutor();
588
+ try {
589
+ // Validate input
590
+ const validatedInput = GitTagsInputSchema.parse(input);
591
+ // Auto-detect context
592
+ const detection = await (0, auto_detection_js_1.autoDetect)(validatedInput.projectPath);
593
+ await (0, auto_detection_js_1.validateAutoDetection)(detection);
594
+ // Execute specific action
595
+ switch (validatedInput.action) {
596
+ case 'create':
597
+ return await executor['executeCreate'](detection, validatedInput);
598
+ case 'list':
599
+ return await executor['executeList'](detection, validatedInput);
600
+ case 'get':
601
+ return await executor['executeGet'](detection, validatedInput);
602
+ case 'delete':
603
+ return await executor['executeDelete'](detection, validatedInput);
604
+ case 'search':
605
+ return await executor['executeSearch'](detection, validatedInput);
606
+ default:
607
+ throw new Error(`Ação '${validatedInput.action}' não suportada`);
608
+ }
481
609
  }
482
610
  catch (error) {
483
- throw new Error(`Falha ao buscar tags: ${error instanceof Error ? error.message : String(error)}`);
611
+ executor.errorHandler.addError(error);
612
+ return executor.errorHandler.toUniversalResponse();
484
613
  }
485
614
  }
486
615
  };