@andrebuzeli/git-mcp 4.0.21 → 5.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.
- package/README.md +59 -32
- package/dist/config.d.ts +0 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -27
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -3
- package/dist/index.js.map +1 -1
- package/dist/providers/gitea-provider.d.ts +5 -5
- package/dist/providers/gitea-provider.d.ts.map +1 -1
- package/dist/providers/gitea-provider.js +75 -220
- package/dist/providers/gitea-provider.js.map +1 -1
- package/dist/providers/github-provider.d.ts +0 -48
- package/dist/providers/github-provider.d.ts.map +1 -1
- package/dist/providers/github-provider.js +805 -849
- package/dist/providers/github-provider.js.map +1 -1
- package/dist/providers/provider-factory.d.ts +1 -1
- package/dist/providers/provider-factory.d.ts.map +1 -1
- package/dist/providers/provider-factory.js +4 -14
- package/dist/providers/provider-factory.js.map +1 -1
- package/dist/providers/types.d.ts +1 -1
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +91 -37
- package/dist/server.js.map +1 -1
- package/dist/tools/git-files.d.ts.map +1 -1
- package/dist/tools/git-files.js +103 -5
- package/dist/tools/git-files.js.map +1 -1
- package/dist/tools/git-sync.d.ts.map +1 -1
- package/dist/tools/git-sync.js +104 -6
- package/dist/tools/git-sync.js.map +1 -1
- package/dist/tools/git-workflow.d.ts +55 -0
- package/dist/tools/git-workflow.d.ts.map +1 -1
- package/dist/tools/git-workflow.js +660 -7
- package/dist/tools/git-workflow.js.map +1 -1
- package/dist/utils/auto-detection.js +1 -1
- package/dist/utils/auto-detection.js.map +1 -1
- package/dist/utils/configuration-error-generator.d.ts +41 -0
- package/dist/utils/configuration-error-generator.d.ts.map +1 -0
- package/dist/utils/configuration-error-generator.js +168 -0
- package/dist/utils/configuration-error-generator.js.map +1 -0
- package/dist/utils/configuration-validator.d.ts +67 -0
- package/dist/utils/configuration-validator.d.ts.map +1 -0
- package/dist/utils/configuration-validator.js +257 -0
- package/dist/utils/configuration-validator.js.map +1 -0
- package/dist/utils/multi-provider-error-handler.d.ts +75 -0
- package/dist/utils/multi-provider-error-handler.d.ts.map +1 -0
- package/dist/utils/multi-provider-error-handler.js +276 -0
- package/dist/utils/multi-provider-error-handler.js.map +1 -0
- package/dist/utils/multi-provider-operation-handler.d.ts +113 -0
- package/dist/utils/multi-provider-operation-handler.d.ts.map +1 -0
- package/dist/utils/multi-provider-operation-handler.js +303 -0
- package/dist/utils/multi-provider-operation-handler.js.map +1 -0
- package/dist/utils/operation-error-handler.d.ts +69 -0
- package/dist/utils/operation-error-handler.d.ts.map +1 -0
- package/dist/utils/operation-error-handler.js +277 -0
- package/dist/utils/operation-error-handler.js.map +1 -0
- package/dist/utils/provider-operation-handler.d.ts +80 -0
- package/dist/utils/provider-operation-handler.d.ts.map +1 -0
- package/dist/utils/provider-operation-handler.js +201 -0
- package/dist/utils/provider-operation-handler.js.map +1 -0
- package/dist/utils/response-helper.js +1 -1
- package/dist/utils/response-helper.js.map +1 -1
- package/package.json +60 -60
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.gitWorkflowTool = void 0;
|
|
4
4
|
const auto_detection_js_1 = require("../utils/auto-detection.js");
|
|
5
|
+
const configuration_validator_js_1 = require("../utils/configuration-validator.js");
|
|
6
|
+
const provider_operation_handler_js_1 = require("../utils/provider-operation-handler.js");
|
|
7
|
+
const operation_error_handler_js_1 = require("../utils/operation-error-handler.js");
|
|
5
8
|
const terminal_controller_js_1 = require("../utils/terminal-controller.js");
|
|
6
9
|
/**
|
|
7
10
|
* Git Workflow Tool - Ferramenta Principal
|
|
@@ -18,13 +21,18 @@ const inputSchema = {
|
|
|
18
21
|
properties: {
|
|
19
22
|
action: {
|
|
20
23
|
type: 'string',
|
|
21
|
-
enum: ['init', 'commit', 'sync', 'status', 'backup'],
|
|
24
|
+
enum: ['init', 'commit', 'sync', 'status', 'backup', 'create', 'list', 'get', 'update', 'delete', 'fork', 'search'],
|
|
22
25
|
description: 'Ação do workflow a executar'
|
|
23
26
|
},
|
|
24
27
|
projectPath: {
|
|
25
28
|
type: 'string',
|
|
26
29
|
description: 'Caminho do projeto (obrigatório)'
|
|
27
30
|
},
|
|
31
|
+
provider: {
|
|
32
|
+
type: 'string',
|
|
33
|
+
enum: ['github', 'gitea', 'both'],
|
|
34
|
+
description: 'Provider para operações remotas (obrigatório para create, list, get, update, delete, fork, search)'
|
|
35
|
+
},
|
|
28
36
|
message: {
|
|
29
37
|
type: 'string',
|
|
30
38
|
description: 'Mensagem de commit (para commit/sync)'
|
|
@@ -36,9 +44,61 @@ const inputSchema = {
|
|
|
36
44
|
remote: {
|
|
37
45
|
type: 'string',
|
|
38
46
|
description: 'Remote para operações (padrão: origin)'
|
|
47
|
+
},
|
|
48
|
+
// Parâmetros para gerenciamento de repositórios
|
|
49
|
+
repoName: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
description: 'Nome do repositório (para create/get/update/delete/fork)'
|
|
52
|
+
},
|
|
53
|
+
description: {
|
|
54
|
+
type: 'string',
|
|
55
|
+
description: 'Descrição do repositório (para create/update)'
|
|
56
|
+
},
|
|
57
|
+
private: {
|
|
58
|
+
type: 'boolean',
|
|
59
|
+
description: 'Repositório privado (para create/update)'
|
|
60
|
+
},
|
|
61
|
+
sourceRepo: {
|
|
62
|
+
type: 'string',
|
|
63
|
+
description: 'Repositório de origem (para fork)'
|
|
64
|
+
},
|
|
65
|
+
searchQuery: {
|
|
66
|
+
type: 'string',
|
|
67
|
+
description: 'Termo de busca (para search)'
|
|
68
|
+
},
|
|
69
|
+
language: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
description: 'Filtrar por linguagem (para search)'
|
|
72
|
+
},
|
|
73
|
+
sort: {
|
|
74
|
+
type: 'string',
|
|
75
|
+
description: 'Ordenar por: stars, updated, created (padrão: stars)'
|
|
76
|
+
},
|
|
77
|
+
order: {
|
|
78
|
+
type: 'string',
|
|
79
|
+
description: 'Ordem: asc, desc (padrão: desc)'
|
|
80
|
+
},
|
|
81
|
+
page: {
|
|
82
|
+
type: 'number',
|
|
83
|
+
description: 'Página para paginação (padrão: 1)'
|
|
84
|
+
},
|
|
85
|
+
perPage: {
|
|
86
|
+
type: 'number',
|
|
87
|
+
description: 'Itens por página (padrão: 30)'
|
|
39
88
|
}
|
|
40
89
|
},
|
|
41
|
-
required: ['action', 'projectPath']
|
|
90
|
+
required: ['action', 'projectPath'],
|
|
91
|
+
// Provider é obrigatório para operações remotas
|
|
92
|
+
if: {
|
|
93
|
+
properties: {
|
|
94
|
+
action: {
|
|
95
|
+
enum: ['create', 'list', 'get', 'update', 'delete', 'fork', 'search']
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
then: {
|
|
100
|
+
required: ['action', 'projectPath', 'provider']
|
|
101
|
+
}
|
|
42
102
|
};
|
|
43
103
|
async function handleInit(projectPath, detection) {
|
|
44
104
|
try {
|
|
@@ -279,19 +339,559 @@ async function handleBackup(projectPath, detection) {
|
|
|
279
339
|
throw new Error(`Falha ao criar backup: ${error instanceof Error ? error.message : String(error)}`);
|
|
280
340
|
}
|
|
281
341
|
}
|
|
342
|
+
// Funções para gerenciamento de repositórios remotos
|
|
343
|
+
async function handleCreateRepo(repoName, description, isPrivate, detection, projectPath, provider) {
|
|
344
|
+
try {
|
|
345
|
+
// Execute both local and remote operations simultaneously
|
|
346
|
+
const results = await Promise.allSettled([
|
|
347
|
+
// Local operation: initialize Git repository
|
|
348
|
+
handleInit(projectPath, detection),
|
|
349
|
+
// Remote operation: create repository on specified provider(s)
|
|
350
|
+
provider_operation_handler_js_1.ProviderOperationHandler.executeOperation(provider, (providerInstance) => providerInstance.createRepository(repoName, description || `Repositório ${repoName}`, isPrivate || false))
|
|
351
|
+
]);
|
|
352
|
+
const localResult = results[0];
|
|
353
|
+
const remoteResult = results[1];
|
|
354
|
+
// Format results
|
|
355
|
+
const localData = localResult.status === 'fulfilled' ? localResult.value : null;
|
|
356
|
+
const localError = localResult.status === 'rejected' ? localResult.reason.message : null;
|
|
357
|
+
const remoteData = remoteResult.status === 'fulfilled' ? remoteResult.value : null;
|
|
358
|
+
const remoteError = remoteResult.status === 'rejected' ? remoteResult.reason.message : null;
|
|
359
|
+
// Determine overall success and message
|
|
360
|
+
const localSuccess = localResult.status === 'fulfilled';
|
|
361
|
+
const remoteSuccess = remoteResult.status === 'fulfilled' && remoteData?.success;
|
|
362
|
+
let message;
|
|
363
|
+
if (localSuccess && remoteSuccess) {
|
|
364
|
+
message = `Repositório '${repoName}' criado com sucesso (local e remoto)`;
|
|
365
|
+
}
|
|
366
|
+
else if (localSuccess && !remoteSuccess) {
|
|
367
|
+
message = `Repositório '${repoName}' criado localmente, falha na criação remota`;
|
|
368
|
+
}
|
|
369
|
+
else if (!localSuccess && remoteSuccess) {
|
|
370
|
+
message = `Repositório '${repoName}' criado remotamente, falha na inicialização local`;
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
message = `Falha ao criar repositório '${repoName}' (local e remoto)`;
|
|
374
|
+
}
|
|
375
|
+
return {
|
|
376
|
+
success: localSuccess || remoteSuccess, // Success if at least one operation succeeded
|
|
377
|
+
action: 'create',
|
|
378
|
+
message,
|
|
379
|
+
data: {
|
|
380
|
+
repoName,
|
|
381
|
+
description: description || `Repositório ${repoName}`,
|
|
382
|
+
private: isPrivate || false,
|
|
383
|
+
local: {
|
|
384
|
+
success: localSuccess,
|
|
385
|
+
data: localData,
|
|
386
|
+
error: localError
|
|
387
|
+
},
|
|
388
|
+
remote: remoteData || {
|
|
389
|
+
success: false,
|
|
390
|
+
error: remoteError || 'Unknown remote operation error'
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
throw new Error(`Falha ao criar repositório: ${error instanceof Error ? error.message : String(error)}`);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
async function handleListRepos(detection, page = 1, perPage = 30, sort = 'updated', provider) {
|
|
400
|
+
try {
|
|
401
|
+
// Execute operation on specified provider(s)
|
|
402
|
+
const result = await provider_operation_handler_js_1.ProviderOperationHandler.executeOperation(provider, (providerInstance) => providerInstance.listRepositories(detection.owner, page, perPage));
|
|
403
|
+
if (!result.success) {
|
|
404
|
+
const errorMessage = 'message' in result
|
|
405
|
+
? result.message
|
|
406
|
+
: ('error' in result ? result.error || 'Failed to list repositories' : 'Unknown error');
|
|
407
|
+
throw new Error(errorMessage);
|
|
408
|
+
}
|
|
409
|
+
// Handle single provider result
|
|
410
|
+
if ('provider' in result && result.data) {
|
|
411
|
+
const repositories = result.data;
|
|
412
|
+
return {
|
|
413
|
+
success: true,
|
|
414
|
+
action: 'list',
|
|
415
|
+
message: `${repositories.length} repositórios encontrados no ${result.provider}`,
|
|
416
|
+
data: {
|
|
417
|
+
repositories,
|
|
418
|
+
total: repositories.length,
|
|
419
|
+
page,
|
|
420
|
+
perPage,
|
|
421
|
+
sort,
|
|
422
|
+
owner: detection.owner,
|
|
423
|
+
provider: result.provider
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
// Handle multi-provider result
|
|
428
|
+
if ('message' in result && typeof result.data === 'object') {
|
|
429
|
+
const multiData = result.data;
|
|
430
|
+
const allRepositories = [];
|
|
431
|
+
const providerResults = {};
|
|
432
|
+
// Collect repositories from all successful providers
|
|
433
|
+
if (multiData.github?.success && multiData.github.data) {
|
|
434
|
+
allRepositories.push(...multiData.github.data);
|
|
435
|
+
providerResults.github = {
|
|
436
|
+
success: true,
|
|
437
|
+
count: multiData.github.data.length,
|
|
438
|
+
repositories: multiData.github.data
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
else if (multiData.github) {
|
|
442
|
+
providerResults.github = {
|
|
443
|
+
success: false,
|
|
444
|
+
error: multiData.github.error
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
if (multiData.gitea?.success && multiData.gitea.data) {
|
|
448
|
+
allRepositories.push(...multiData.gitea.data);
|
|
449
|
+
providerResults.gitea = {
|
|
450
|
+
success: true,
|
|
451
|
+
count: multiData.gitea.data.length,
|
|
452
|
+
repositories: multiData.gitea.data
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
else if (multiData.gitea) {
|
|
456
|
+
providerResults.gitea = {
|
|
457
|
+
success: false,
|
|
458
|
+
error: multiData.gitea.error
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
success: true,
|
|
463
|
+
action: 'list',
|
|
464
|
+
message: result.message,
|
|
465
|
+
data: {
|
|
466
|
+
repositories: allRepositories,
|
|
467
|
+
total: allRepositories.length,
|
|
468
|
+
page,
|
|
469
|
+
perPage,
|
|
470
|
+
sort,
|
|
471
|
+
owner: detection.owner,
|
|
472
|
+
provider: 'both',
|
|
473
|
+
providerResults,
|
|
474
|
+
warnings: result.warnings
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
throw new Error('Unexpected result format from provider operation');
|
|
479
|
+
}
|
|
480
|
+
catch (error) {
|
|
481
|
+
throw new Error(`Falha ao listar repositórios: ${error instanceof Error ? error.message : String(error)}`);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
async function handleGetRepo(repoName, detection, provider) {
|
|
485
|
+
try {
|
|
486
|
+
// Execute operation on specified provider(s)
|
|
487
|
+
const result = await provider_operation_handler_js_1.ProviderOperationHandler.executeOperation(provider, (providerInstance) => providerInstance.getRepository(detection.owner, repoName));
|
|
488
|
+
if (!result.success) {
|
|
489
|
+
const errorMessage = 'message' in result
|
|
490
|
+
? result.message
|
|
491
|
+
: ('error' in result ? result.error || 'Failed to get repository' : 'Unknown error');
|
|
492
|
+
throw new Error(errorMessage);
|
|
493
|
+
}
|
|
494
|
+
// Handle single provider result
|
|
495
|
+
if ('provider' in result && result.data) {
|
|
496
|
+
return {
|
|
497
|
+
success: true,
|
|
498
|
+
action: 'get',
|
|
499
|
+
message: `Detalhes do repositório '${repoName}' obtidos do ${result.provider}`,
|
|
500
|
+
data: {
|
|
501
|
+
repository: result.data,
|
|
502
|
+
provider: result.provider
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
// Handle multi-provider result
|
|
507
|
+
if ('message' in result && typeof result.data === 'object') {
|
|
508
|
+
const multiData = result.data;
|
|
509
|
+
const repositories = {};
|
|
510
|
+
if (multiData.github?.success && multiData.github.data) {
|
|
511
|
+
repositories.github = multiData.github.data;
|
|
512
|
+
}
|
|
513
|
+
if (multiData.gitea?.success && multiData.gitea.data) {
|
|
514
|
+
repositories.gitea = multiData.gitea.data;
|
|
515
|
+
}
|
|
516
|
+
return {
|
|
517
|
+
success: true,
|
|
518
|
+
action: 'get',
|
|
519
|
+
message: result.message,
|
|
520
|
+
data: {
|
|
521
|
+
repositories,
|
|
522
|
+
provider: 'both',
|
|
523
|
+
providerResults: {
|
|
524
|
+
github: multiData.github ? {
|
|
525
|
+
success: multiData.github.success,
|
|
526
|
+
error: multiData.github.error
|
|
527
|
+
} : undefined,
|
|
528
|
+
gitea: multiData.gitea ? {
|
|
529
|
+
success: multiData.gitea.success,
|
|
530
|
+
error: multiData.gitea.error
|
|
531
|
+
} : undefined
|
|
532
|
+
},
|
|
533
|
+
warnings: 'warnings' in result ? result.warnings : undefined
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
throw new Error('Unexpected result format from provider operation');
|
|
538
|
+
}
|
|
539
|
+
catch (error) {
|
|
540
|
+
throw new Error(`Falha ao obter repositório: ${error instanceof Error ? error.message : String(error)}`);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
async function handleSearchRepos(searchQuery, detection, provider, language, sort = 'stars', order = 'desc') {
|
|
544
|
+
try {
|
|
545
|
+
// Execute operation on specified provider(s)
|
|
546
|
+
const result = await provider_operation_handler_js_1.ProviderOperationHandler.executeOperation(provider, (providerInstance) => providerInstance.searchRepositories(searchQuery));
|
|
547
|
+
if (!result.success) {
|
|
548
|
+
const errorMessage = 'message' in result
|
|
549
|
+
? result.message
|
|
550
|
+
: ('error' in result ? result.error || 'Failed to search repositories' : 'Unknown error');
|
|
551
|
+
throw new Error(errorMessage);
|
|
552
|
+
}
|
|
553
|
+
// Handle single provider result
|
|
554
|
+
if ('provider' in result && result.data) {
|
|
555
|
+
const searchResults = result.data;
|
|
556
|
+
return {
|
|
557
|
+
success: true,
|
|
558
|
+
action: 'search',
|
|
559
|
+
message: `${searchResults.length} repositórios encontrados para '${searchQuery}' no ${result.provider}`,
|
|
560
|
+
data: {
|
|
561
|
+
query: searchQuery,
|
|
562
|
+
language,
|
|
563
|
+
sort,
|
|
564
|
+
order,
|
|
565
|
+
results: searchResults,
|
|
566
|
+
total: searchResults.length,
|
|
567
|
+
provider: result.provider
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
// Handle multi-provider result
|
|
572
|
+
if ('message' in result && typeof result.data === 'object') {
|
|
573
|
+
const multiData = result.data;
|
|
574
|
+
const allResults = [];
|
|
575
|
+
const providerResults = {};
|
|
576
|
+
// Collect results from all successful providers
|
|
577
|
+
if (multiData.github?.success && multiData.github.data) {
|
|
578
|
+
const githubResults = multiData.github.data.map((repo) => ({
|
|
579
|
+
...repo,
|
|
580
|
+
source: 'github'
|
|
581
|
+
}));
|
|
582
|
+
allResults.push(...githubResults);
|
|
583
|
+
providerResults.github = {
|
|
584
|
+
success: true,
|
|
585
|
+
count: multiData.github.data.length,
|
|
586
|
+
results: multiData.github.data
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
else if (multiData.github) {
|
|
590
|
+
providerResults.github = {
|
|
591
|
+
success: false,
|
|
592
|
+
error: multiData.github.error
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
if (multiData.gitea?.success && multiData.gitea.data) {
|
|
596
|
+
const giteaResults = multiData.gitea.data.map((repo) => ({
|
|
597
|
+
...repo,
|
|
598
|
+
source: 'gitea'
|
|
599
|
+
}));
|
|
600
|
+
allResults.push(...giteaResults);
|
|
601
|
+
providerResults.gitea = {
|
|
602
|
+
success: true,
|
|
603
|
+
count: multiData.gitea.data.length,
|
|
604
|
+
results: multiData.gitea.data
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
else if (multiData.gitea) {
|
|
608
|
+
providerResults.gitea = {
|
|
609
|
+
success: false,
|
|
610
|
+
error: multiData.gitea.error
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
return {
|
|
614
|
+
success: true,
|
|
615
|
+
action: 'search',
|
|
616
|
+
message: result.message,
|
|
617
|
+
data: {
|
|
618
|
+
query: searchQuery,
|
|
619
|
+
language,
|
|
620
|
+
sort,
|
|
621
|
+
order,
|
|
622
|
+
results: allResults,
|
|
623
|
+
total: allResults.length,
|
|
624
|
+
provider: 'both',
|
|
625
|
+
providerResults,
|
|
626
|
+
warnings: 'warnings' in result ? result.warnings : undefined
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
throw new Error('Unexpected result format from provider operation');
|
|
631
|
+
}
|
|
632
|
+
catch (error) {
|
|
633
|
+
throw new Error(`Falha na busca: ${error instanceof Error ? error.message : String(error)}`);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
async function handleUpdateRepo(repoName, detection, provider, description, isPrivate) {
|
|
637
|
+
try {
|
|
638
|
+
// Prepare update data
|
|
639
|
+
const updateData = {};
|
|
640
|
+
if (description !== undefined)
|
|
641
|
+
updateData.description = description;
|
|
642
|
+
if (isPrivate !== undefined)
|
|
643
|
+
updateData.private = isPrivate;
|
|
644
|
+
// Execute operation on specified provider(s)
|
|
645
|
+
const result = await provider_operation_handler_js_1.ProviderOperationHandler.executeOperation(provider, (providerInstance) => providerInstance.updateRepository(detection.owner, repoName, updateData));
|
|
646
|
+
if (!result.success) {
|
|
647
|
+
const errorMessage = 'message' in result
|
|
648
|
+
? result.message
|
|
649
|
+
: ('error' in result ? result.error || 'Failed to update repository' : 'Unknown error');
|
|
650
|
+
throw new Error(errorMessage);
|
|
651
|
+
}
|
|
652
|
+
// Handle single provider result
|
|
653
|
+
if ('provider' in result && result.data) {
|
|
654
|
+
return {
|
|
655
|
+
success: true,
|
|
656
|
+
action: 'update',
|
|
657
|
+
message: `Repositório '${repoName}' atualizado com sucesso no ${result.provider}`,
|
|
658
|
+
data: {
|
|
659
|
+
repoUpdated: true,
|
|
660
|
+
repository: result.data,
|
|
661
|
+
provider: result.provider
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
// Handle multi-provider result
|
|
666
|
+
if ('message' in result && typeof result.data === 'object') {
|
|
667
|
+
const multiData = result.data;
|
|
668
|
+
const updatedRepositories = {};
|
|
669
|
+
if (multiData.github?.success && multiData.github.data) {
|
|
670
|
+
updatedRepositories.github = multiData.github.data;
|
|
671
|
+
}
|
|
672
|
+
if (multiData.gitea?.success && multiData.gitea.data) {
|
|
673
|
+
updatedRepositories.gitea = multiData.gitea.data;
|
|
674
|
+
}
|
|
675
|
+
return {
|
|
676
|
+
success: true,
|
|
677
|
+
action: 'update',
|
|
678
|
+
message: result.message,
|
|
679
|
+
data: {
|
|
680
|
+
repoUpdated: true,
|
|
681
|
+
repositories: updatedRepositories,
|
|
682
|
+
provider: 'both',
|
|
683
|
+
providerResults: {
|
|
684
|
+
github: multiData.github ? {
|
|
685
|
+
success: multiData.github.success,
|
|
686
|
+
error: multiData.github.error
|
|
687
|
+
} : undefined,
|
|
688
|
+
gitea: multiData.gitea ? {
|
|
689
|
+
success: multiData.gitea.success,
|
|
690
|
+
error: multiData.gitea.error
|
|
691
|
+
} : undefined
|
|
692
|
+
},
|
|
693
|
+
warnings: 'warnings' in result ? result.warnings : undefined
|
|
694
|
+
}
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
throw new Error('Unexpected result format from provider operation');
|
|
698
|
+
}
|
|
699
|
+
catch (error) {
|
|
700
|
+
throw new Error(`Falha ao atualizar repositório: ${error instanceof Error ? error.message : String(error)}`);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
async function handleDeleteRepo(repoName, detection, provider) {
|
|
704
|
+
try {
|
|
705
|
+
// Execute operation on specified provider(s)
|
|
706
|
+
const result = await provider_operation_handler_js_1.ProviderOperationHandler.executeOperation(provider, (providerInstance) => providerInstance.deleteRepository(detection.owner, repoName));
|
|
707
|
+
if (!result.success) {
|
|
708
|
+
const errorMessage = 'message' in result
|
|
709
|
+
? result.message
|
|
710
|
+
: ('error' in result ? result.error || 'Failed to delete repository' : 'Unknown error');
|
|
711
|
+
throw new Error(errorMessage);
|
|
712
|
+
}
|
|
713
|
+
const deletedAt = new Date().toISOString();
|
|
714
|
+
// Handle single provider result
|
|
715
|
+
if ('provider' in result) {
|
|
716
|
+
return {
|
|
717
|
+
success: true,
|
|
718
|
+
action: 'delete',
|
|
719
|
+
message: `Repositório '${repoName}' removido com sucesso do ${result.provider}`,
|
|
720
|
+
data: {
|
|
721
|
+
repoDeleted: true,
|
|
722
|
+
repoName,
|
|
723
|
+
owner: detection.owner,
|
|
724
|
+
provider: result.provider,
|
|
725
|
+
deletedAt,
|
|
726
|
+
warning: 'Esta ação é irreversível'
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
// Handle multi-provider result
|
|
731
|
+
if ('data' in result && typeof result.data === 'object') {
|
|
732
|
+
const multiData = result.data;
|
|
733
|
+
const deletionResults = {};
|
|
734
|
+
if (multiData.github) {
|
|
735
|
+
deletionResults.github = {
|
|
736
|
+
success: multiData.github.success,
|
|
737
|
+
error: multiData.github.error
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
if (multiData.gitea) {
|
|
741
|
+
deletionResults.gitea = {
|
|
742
|
+
success: multiData.gitea.success,
|
|
743
|
+
error: multiData.gitea.error
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
return {
|
|
747
|
+
success: true,
|
|
748
|
+
action: 'delete',
|
|
749
|
+
message: result.message,
|
|
750
|
+
data: {
|
|
751
|
+
repoDeleted: true,
|
|
752
|
+
repoName,
|
|
753
|
+
owner: detection.owner,
|
|
754
|
+
provider: 'both',
|
|
755
|
+
deletionResults,
|
|
756
|
+
deletedAt,
|
|
757
|
+
warning: 'Esta ação é irreversível',
|
|
758
|
+
warnings: 'warnings' in result ? result.warnings : undefined
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
throw new Error('Unexpected result format from provider operation');
|
|
763
|
+
}
|
|
764
|
+
catch (error) {
|
|
765
|
+
throw new Error(`Falha ao remover repositório: ${error instanceof Error ? error.message : String(error)}`);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
async function handleForkRepo(sourceRepo, newRepoName, detection, provider) {
|
|
769
|
+
try {
|
|
770
|
+
// Parse sourceRepo (format: owner/repo)
|
|
771
|
+
const [sourceOwner, sourceRepoName] = sourceRepo.split('/');
|
|
772
|
+
if (!sourceOwner || !sourceRepoName) {
|
|
773
|
+
throw new Error('sourceRepo deve estar no formato "owner/repo"');
|
|
774
|
+
}
|
|
775
|
+
const forkName = newRepoName || sourceRepoName;
|
|
776
|
+
// Execute operation on specified provider(s)
|
|
777
|
+
const result = await provider_operation_handler_js_1.ProviderOperationHandler.executeOperation(provider, (providerInstance) => providerInstance.forkRepository(sourceOwner, sourceRepoName));
|
|
778
|
+
if (!result.success) {
|
|
779
|
+
const errorMessage = 'message' in result
|
|
780
|
+
? result.message
|
|
781
|
+
: ('error' in result ? result.error || 'Failed to fork repository' : 'Unknown error');
|
|
782
|
+
throw new Error(errorMessage);
|
|
783
|
+
}
|
|
784
|
+
// Handle single provider result
|
|
785
|
+
if ('provider' in result && result.data) {
|
|
786
|
+
return {
|
|
787
|
+
success: true,
|
|
788
|
+
action: 'fork',
|
|
789
|
+
message: `Fork '${forkName}' criado com sucesso de '${sourceRepo}' no ${result.provider}`,
|
|
790
|
+
data: {
|
|
791
|
+
repoForked: true,
|
|
792
|
+
originalRepo: sourceRepo,
|
|
793
|
+
forkName,
|
|
794
|
+
repository: result.data,
|
|
795
|
+
provider: result.provider
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
// Handle multi-provider result
|
|
800
|
+
if ('message' in result && typeof result.data === 'object') {
|
|
801
|
+
const multiData = result.data;
|
|
802
|
+
const forkedRepositories = {};
|
|
803
|
+
if (multiData.github?.success && multiData.github.data) {
|
|
804
|
+
forkedRepositories.github = multiData.github.data;
|
|
805
|
+
}
|
|
806
|
+
if (multiData.gitea?.success && multiData.gitea.data) {
|
|
807
|
+
forkedRepositories.gitea = multiData.gitea.data;
|
|
808
|
+
}
|
|
809
|
+
return {
|
|
810
|
+
success: true,
|
|
811
|
+
action: 'fork',
|
|
812
|
+
message: result.message,
|
|
813
|
+
data: {
|
|
814
|
+
repoForked: true,
|
|
815
|
+
originalRepo: sourceRepo,
|
|
816
|
+
forkName,
|
|
817
|
+
repositories: forkedRepositories,
|
|
818
|
+
provider: 'both',
|
|
819
|
+
providerResults: {
|
|
820
|
+
github: multiData.github ? {
|
|
821
|
+
success: multiData.github.success,
|
|
822
|
+
error: multiData.github.error
|
|
823
|
+
} : undefined,
|
|
824
|
+
gitea: multiData.gitea ? {
|
|
825
|
+
success: multiData.gitea.success,
|
|
826
|
+
error: multiData.gitea.error
|
|
827
|
+
} : undefined
|
|
828
|
+
},
|
|
829
|
+
warnings: 'warnings' in result ? result.warnings : undefined
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
throw new Error('Unexpected result format from provider operation');
|
|
834
|
+
}
|
|
835
|
+
catch (error) {
|
|
836
|
+
throw new Error(`Falha ao criar fork: ${error instanceof Error ? error.message : String(error)}`);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
282
839
|
exports.gitWorkflowTool = {
|
|
283
840
|
name: 'git-workflow',
|
|
284
|
-
description: '🔄 WORKFLOW
|
|
841
|
+
description: '🔄 WORKFLOW COMPLETO - Operações Git locais + gerenciamento completo de repositórios remotos: init, commit, sync, status, backup, create, list, get, update, delete, fork, search',
|
|
285
842
|
inputSchema,
|
|
286
843
|
async handler(input) {
|
|
287
844
|
try {
|
|
288
|
-
const { action, projectPath, message, branch, remote } = input;
|
|
845
|
+
const { action, projectPath, provider, message, branch, remote, repoName, description, private: isPrivate, sourceRepo, searchQuery, language, sort, order, page, perPage } = input;
|
|
289
846
|
if (!projectPath) {
|
|
290
847
|
throw new Error('projectPath é obrigatório');
|
|
291
848
|
}
|
|
849
|
+
// Define remote operations that require provider parameter
|
|
850
|
+
const remoteOperations = ['create', 'list', 'get', 'update', 'delete', 'fork', 'search'];
|
|
851
|
+
// Validate provider parameter for remote operations
|
|
852
|
+
if (remoteOperations.includes(action)) {
|
|
853
|
+
if (!provider) {
|
|
854
|
+
const detection = (0, auto_detection_js_1.autoDetect)(projectPath);
|
|
855
|
+
return (0, auto_detection_js_1.createUniversalResponse)(false, action, 'Provider parameter is required for remote operations', detection, 'git-workflow', undefined, {
|
|
856
|
+
code: 'MISSING_PROVIDER_PARAMETER',
|
|
857
|
+
message: 'Provider parameter is required for remote operations',
|
|
858
|
+
cause: 'Provider parameter not provided for remote operation',
|
|
859
|
+
suggestion: 'Add provider parameter with one of: github, gitea, both'
|
|
860
|
+
});
|
|
861
|
+
}
|
|
862
|
+
// Validate provider parameter value
|
|
863
|
+
const providerValidation = configuration_validator_js_1.ConfigurationValidator.validateProvider(provider);
|
|
864
|
+
if (!providerValidation.valid) {
|
|
865
|
+
const detection = (0, auto_detection_js_1.autoDetect)(projectPath);
|
|
866
|
+
return (0, auto_detection_js_1.createUniversalResponse)(false, action, providerValidation.error.message, detection, 'git-workflow', undefined, {
|
|
867
|
+
code: providerValidation.error.code,
|
|
868
|
+
message: providerValidation.error.message,
|
|
869
|
+
cause: 'Invalid provider parameter value',
|
|
870
|
+
suggestion: providerValidation.error.suggestion
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
// Validate provider configuration
|
|
874
|
+
const configValidation = configuration_validator_js_1.ConfigurationValidator.validateProviderConfiguration(provider);
|
|
875
|
+
if (!configValidation.valid) {
|
|
876
|
+
const detection = (0, auto_detection_js_1.autoDetect)(projectPath);
|
|
877
|
+
const errorMessage = configuration_validator_js_1.ConfigurationValidator.formatValidationError(configValidation);
|
|
878
|
+
// Create comprehensive error response for configuration issues
|
|
879
|
+
const configError = configValidation.error.configuration;
|
|
880
|
+
const enhancedMessage = configError
|
|
881
|
+
? `${configValidation.error.message}\n\n${configuration_validator_js_1.ConfigurationValidator.formatValidationError(configValidation)}`
|
|
882
|
+
: configValidation.error.message;
|
|
883
|
+
return (0, auto_detection_js_1.createUniversalResponse)(false, action, enhancedMessage, detection, 'git-workflow', undefined, {
|
|
884
|
+
code: configValidation.error.code,
|
|
885
|
+
message: errorMessage,
|
|
886
|
+
cause: 'Provider configuration validation failed',
|
|
887
|
+
suggestion: configValidation.error.suggestion
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
}
|
|
292
891
|
const detection = (0, auto_detection_js_1.autoDetect)(projectPath);
|
|
293
892
|
let result;
|
|
294
893
|
switch (action) {
|
|
894
|
+
// Operações Git locais
|
|
295
895
|
case 'init':
|
|
296
896
|
result = await handleInit(projectPath, detection);
|
|
297
897
|
break;
|
|
@@ -313,16 +913,69 @@ exports.gitWorkflowTool = {
|
|
|
313
913
|
case 'backup':
|
|
314
914
|
result = await handleBackup(projectPath, detection);
|
|
315
915
|
break;
|
|
916
|
+
// Gerenciamento de repositórios remotos
|
|
917
|
+
case 'create':
|
|
918
|
+
if (!repoName) {
|
|
919
|
+
throw new Error('repoName é obrigatório para create');
|
|
920
|
+
}
|
|
921
|
+
result = await handleCreateRepo(repoName, description || '', isPrivate || false, detection, projectPath, provider);
|
|
922
|
+
break;
|
|
923
|
+
case 'list':
|
|
924
|
+
result = await handleListRepos(detection, page, perPage, sort, provider);
|
|
925
|
+
break;
|
|
926
|
+
case 'get':
|
|
927
|
+
if (!repoName) {
|
|
928
|
+
throw new Error('repoName é obrigatório para get');
|
|
929
|
+
}
|
|
930
|
+
result = await handleGetRepo(repoName, detection, provider);
|
|
931
|
+
break;
|
|
932
|
+
case 'search':
|
|
933
|
+
if (!searchQuery) {
|
|
934
|
+
throw new Error('searchQuery é obrigatório para search');
|
|
935
|
+
}
|
|
936
|
+
result = await handleSearchRepos(searchQuery, detection, provider, language, sort, order);
|
|
937
|
+
break;
|
|
938
|
+
case 'update':
|
|
939
|
+
if (!repoName) {
|
|
940
|
+
throw new Error('repoName é obrigatório para update');
|
|
941
|
+
}
|
|
942
|
+
result = await handleUpdateRepo(repoName, detection, provider, description, isPrivate);
|
|
943
|
+
break;
|
|
944
|
+
case 'delete':
|
|
945
|
+
if (!repoName) {
|
|
946
|
+
throw new Error('repoName é obrigatório para delete');
|
|
947
|
+
}
|
|
948
|
+
result = await handleDeleteRepo(repoName, detection, provider);
|
|
949
|
+
break;
|
|
950
|
+
case 'fork':
|
|
951
|
+
if (!sourceRepo) {
|
|
952
|
+
throw new Error('sourceRepo é obrigatório para fork');
|
|
953
|
+
}
|
|
954
|
+
result = await handleForkRepo(sourceRepo, repoName, detection, provider);
|
|
955
|
+
break;
|
|
316
956
|
default:
|
|
317
|
-
throw new Error(`Ação '${action}' não suportada. Use: init, commit, sync, status, backup`);
|
|
957
|
+
throw new Error(`Ação '${action}' não suportada. Use: init, commit, sync, status, backup, create, list, get, update, delete, fork, search`);
|
|
318
958
|
}
|
|
319
959
|
return (0, auto_detection_js_1.createUniversalResponse)(result.success, action, result.message, detection, 'git-workflow', result.data);
|
|
320
960
|
}
|
|
321
961
|
catch (error) {
|
|
322
962
|
const detection = (0, auto_detection_js_1.autoDetect)(input.projectPath || '');
|
|
323
|
-
|
|
963
|
+
const errorInstance = error instanceof Error ? error : new Error(String(error));
|
|
964
|
+
// For remote operations, provide comprehensive error handling
|
|
965
|
+
const remoteOperations = ['create', 'list', 'get', 'update', 'delete', 'fork', 'search'];
|
|
966
|
+
if (remoteOperations.includes(input.action) && input.provider) {
|
|
967
|
+
const operationError = operation_error_handler_js_1.OperationErrorHandler.analyzeAndHandleError(errorInstance, input.provider, input.action);
|
|
968
|
+
return (0, auto_detection_js_1.createUniversalResponse)(false, input.action || 'unknown', operationError.message, detection, 'git-workflow', undefined, {
|
|
969
|
+
code: operationError.code,
|
|
970
|
+
message: operation_error_handler_js_1.OperationErrorHandler.formatErrorMessage(operationError),
|
|
971
|
+
cause: operationError.cause,
|
|
972
|
+
suggestion: operationError.solution
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
// For local operations, provide generic error handling
|
|
976
|
+
return (0, auto_detection_js_1.createUniversalResponse)(false, input.action || 'unknown', errorInstance.message, detection, 'git-workflow', undefined, {
|
|
324
977
|
code: 'WORKFLOW_ERROR',
|
|
325
|
-
message:
|
|
978
|
+
message: errorInstance.message,
|
|
326
979
|
cause: 'Erro na execução do workflow Git',
|
|
327
980
|
suggestion: 'Verifique os parâmetros e tente novamente'
|
|
328
981
|
});
|