@andrebuzeli/git-mcp 10.0.9 → 11.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 +34 -428
- package/bin/git-mcp.js +21 -0
- package/docs/TOOLS.md +110 -0
- package/mcp.json.template +12 -0
- package/package.json +9 -76
- package/src/local/git.js +14 -0
- package/src/providers/gitea.js +13 -0
- package/src/providers/github.js +13 -0
- package/src/server.js +63 -0
- package/src/tools/git-actions.js +19 -0
- package/src/tools/git-activity.js +28 -0
- package/src/tools/git-admin.js +20 -0
- package/src/tools/git-checks.js +14 -0
- package/src/tools/git-commits.js +34 -0
- package/src/tools/git-contents.js +30 -0
- package/src/tools/git-deployments.js +21 -0
- package/src/tools/git-gists.js +15 -0
- package/src/tools/git-gitdata.js +19 -0
- package/src/tools/git-issues-prs.js +44 -0
- package/src/tools/git-issues.js +12 -0
- package/src/tools/git-local.js +66 -0
- package/src/tools/git-meta.js +19 -0
- package/src/tools/git-misc.js +21 -0
- package/src/tools/git-orgs.js +26 -0
- package/src/tools/git-packages.js +12 -0
- package/src/tools/git-raw.js +14 -0
- package/src/tools/git-releases.js +17 -0
- package/src/tools/git-remote.js +29 -0
- package/src/tools/git-repos.js +60 -0
- package/src/tools/git-search.js +18 -0
- package/src/tools/git-sync.js +40 -0
- package/src/tools/git-user.js +26 -0
- package/src/tools/schema.js +3 -0
- package/src/utils/fs.js +29 -0
- package/src/utils/project.js +7 -0
- package/tests/errors.js +26 -0
- package/tests/full_suite.js +98 -0
- package/tests/run.js +50 -0
- package/LICENSE +0 -21
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -224
- package/dist/prompts/gitPrompts.d.ts +0 -93
- package/dist/prompts/gitPrompts.js +0 -177
- package/dist/providers/giteaProvider.d.ts +0 -3
- package/dist/providers/giteaProvider.js +0 -6
- package/dist/providers/githubProvider.d.ts +0 -2
- package/dist/providers/githubProvider.js +0 -4
- package/dist/providers/providerManager.d.ts +0 -11
- package/dist/providers/providerManager.js +0 -49
- package/dist/resources/toolsGuide.d.ts +0 -12
- package/dist/resources/toolsGuide.js +0 -1713
- package/dist/scripts/test_e2e.d.ts +0 -1
- package/dist/scripts/test_e2e.js +0 -199
- package/dist/scripts/test_exhaustive.d.ts +0 -1
- package/dist/scripts/test_exhaustive.js +0 -275
- package/dist/scripts/test_gitea_creation.d.ts +0 -1
- package/dist/scripts/test_gitea_creation.js +0 -116
- package/dist/scripts/verify_setup.d.ts +0 -1
- package/dist/scripts/verify_setup.js +0 -61
- package/dist/server.d.ts +0 -9
- package/dist/server.js +0 -73
- package/dist/tools/gitAnalytics.d.ts +0 -35
- package/dist/tools/gitAnalytics.js +0 -220
- package/dist/tools/gitArchive.d.ts +0 -119
- package/dist/tools/gitArchive.js +0 -150
- package/dist/tools/gitBackup.d.ts +0 -116
- package/dist/tools/gitBackup.js +0 -156
- package/dist/tools/gitBranches.d.ts +0 -54
- package/dist/tools/gitBranches.js +0 -282
- package/dist/tools/gitChangelog.d.ts +0 -37
- package/dist/tools/gitChangelog.js +0 -67
- package/dist/tools/gitConfig.d.ts +0 -97
- package/dist/tools/gitConfig.js +0 -125
- package/dist/tools/gitFiles.d.ts +0 -129
- package/dist/tools/gitFiles.js +0 -213
- package/dist/tools/gitFix.d.ts +0 -4
- package/dist/tools/gitFix.js +0 -159
- package/dist/tools/gitFix.tool.d.ts +0 -31
- package/dist/tools/gitFix.tool.js +0 -92
- package/dist/tools/gitHistory.d.ts +0 -41
- package/dist/tools/gitHistory.js +0 -349
- package/dist/tools/gitIgnore.d.ts +0 -214
- package/dist/tools/gitIgnore.js +0 -338
- package/dist/tools/gitIssues.d.ts +0 -80
- package/dist/tools/gitIssues.js +0 -363
- package/dist/tools/gitLog.d.ts +0 -30
- package/dist/tools/gitLog.js +0 -46
- package/dist/tools/gitMonitor.d.ts +0 -30
- package/dist/tools/gitMonitor.js +0 -284
- package/dist/tools/gitPackages.d.ts +0 -180
- package/dist/tools/gitPackages.js +0 -214
- package/dist/tools/gitPulls.d.ts +0 -66
- package/dist/tools/gitPulls.js +0 -347
- package/dist/tools/gitPush.d.ts +0 -40
- package/dist/tools/gitPush.js +0 -59
- package/dist/tools/gitRelease.d.ts +0 -49
- package/dist/tools/gitRelease.js +0 -359
- package/dist/tools/gitRemote.d.ts +0 -47
- package/dist/tools/gitRemote.js +0 -111
- package/dist/tools/gitReset.d.ts +0 -57
- package/dist/tools/gitReset.js +0 -79
- package/dist/tools/gitStash.d.ts +0 -61
- package/dist/tools/gitStash.js +0 -80
- package/dist/tools/gitSync.d.ts +0 -34
- package/dist/tools/gitSync.js +0 -182
- package/dist/tools/gitTags.d.ts +0 -45
- package/dist/tools/gitTags.js +0 -251
- package/dist/tools/gitUpdate.d.ts +0 -60
- package/dist/tools/gitUpdate.js +0 -474
- package/dist/tools/gitUpload.d.ts +0 -35
- package/dist/tools/gitUpload.js +0 -385
- package/dist/tools/gitWorkflow.d.ts +0 -117
- package/dist/tools/gitWorkflow.js +0 -472
- package/dist/types.d.ts +0 -20
- package/dist/types.js +0 -1
- package/dist/utils/agentHelpers.d.ts +0 -11
- package/dist/utils/agentHelpers.js +0 -41
- package/dist/utils/apiHelpers.d.ts +0 -29
- package/dist/utils/apiHelpers.js +0 -125
- package/dist/utils/cache.d.ts +0 -96
- package/dist/utils/cache.js +0 -208
- package/dist/utils/contextDetector.d.ts +0 -0
- package/dist/utils/contextDetector.js +0 -1
- package/dist/utils/errors.d.ts +0 -13
- package/dist/utils/errors.js +0 -17
- package/dist/utils/gitAdapter.d.ts +0 -224
- package/dist/utils/gitAdapter.js +0 -1162
- package/dist/utils/logger.d.ts +0 -45
- package/dist/utils/logger.js +0 -140
- package/dist/utils/rateLimiter.d.ts +0 -113
- package/dist/utils/rateLimiter.js +0 -257
- package/dist/utils/repoHelpers.d.ts +0 -44
- package/dist/utils/repoHelpers.js +0 -122
- package/dist/utils/safetyController.d.ts +0 -1
- package/dist/utils/safetyController.js +0 -12
- package/dist/utils/validation.d.ts +0 -115
- package/dist/utils/validation.js +0 -270
package/dist/utils/logger.d.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sistema de logging aprimorado para Git-MCP
|
|
3
|
-
* Fornece diferentes níveis de log com rotação e sanitização
|
|
4
|
-
*/
|
|
5
|
-
export declare enum LogLevel {
|
|
6
|
-
ERROR = 0,
|
|
7
|
-
WARN = 1,
|
|
8
|
-
INFO = 2,
|
|
9
|
-
DEBUG = 3
|
|
10
|
-
}
|
|
11
|
-
export interface LogEntry {
|
|
12
|
-
timestamp: string;
|
|
13
|
-
level: LogLevel;
|
|
14
|
-
message: string;
|
|
15
|
-
data?: any;
|
|
16
|
-
tool?: string;
|
|
17
|
-
userAgent?: string;
|
|
18
|
-
}
|
|
19
|
-
export declare class Logger {
|
|
20
|
-
private static instance;
|
|
21
|
-
private logLevel;
|
|
22
|
-
private maxEntries;
|
|
23
|
-
private logs;
|
|
24
|
-
private constructor();
|
|
25
|
-
static getInstance(): Logger;
|
|
26
|
-
/**
|
|
27
|
-
* Sanitiza dados sensíveis antes de logar
|
|
28
|
-
*/
|
|
29
|
-
private sanitizeData;
|
|
30
|
-
private formatMessage;
|
|
31
|
-
private addLog;
|
|
32
|
-
error(message: string, data?: any, tool?: string): void;
|
|
33
|
-
warn(message: string, data?: any, tool?: string): void;
|
|
34
|
-
info(message: string, data?: any, tool?: string): void;
|
|
35
|
-
debug(message: string, data?: any, tool?: string): void;
|
|
36
|
-
getRecentLogs(level?: LogLevel, limit?: number): LogEntry[];
|
|
37
|
-
clearLogs(): void;
|
|
38
|
-
setLogLevel(level: LogLevel): void;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Helper functions para logging em diferentes contextos
|
|
42
|
-
*/
|
|
43
|
-
export declare function logToolExecution(toolName: string, args: any, result?: any, error?: Error): void;
|
|
44
|
-
export declare function logSecurityEvent(event: string, details: any): void;
|
|
45
|
-
export declare function logPerformanceMetric(operation: string, duration: number, details?: any): void;
|
package/dist/utils/logger.js
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sistema de logging aprimorado para Git-MCP
|
|
3
|
-
* Fornece diferentes níveis de log com rotação e sanitização
|
|
4
|
-
*/
|
|
5
|
-
export var LogLevel;
|
|
6
|
-
(function (LogLevel) {
|
|
7
|
-
LogLevel[LogLevel["ERROR"] = 0] = "ERROR";
|
|
8
|
-
LogLevel[LogLevel["WARN"] = 1] = "WARN";
|
|
9
|
-
LogLevel[LogLevel["INFO"] = 2] = "INFO";
|
|
10
|
-
LogLevel[LogLevel["DEBUG"] = 3] = "DEBUG";
|
|
11
|
-
})(LogLevel || (LogLevel = {}));
|
|
12
|
-
export class Logger {
|
|
13
|
-
constructor(logLevel = LogLevel.INFO, maxEntries = 1000) {
|
|
14
|
-
this.logLevel = logLevel;
|
|
15
|
-
this.maxEntries = maxEntries;
|
|
16
|
-
this.logs = [];
|
|
17
|
-
}
|
|
18
|
-
static getInstance() {
|
|
19
|
-
if (!Logger.instance) {
|
|
20
|
-
const debugMode = process.env.DEBUG === 'true';
|
|
21
|
-
Logger.instance = new Logger(debugMode ? LogLevel.DEBUG : LogLevel.INFO);
|
|
22
|
-
}
|
|
23
|
-
return Logger.instance;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Sanitiza dados sensíveis antes de logar
|
|
27
|
-
*/
|
|
28
|
-
sanitizeData(data) {
|
|
29
|
-
if (!data || typeof data !== 'object') {
|
|
30
|
-
return data;
|
|
31
|
-
}
|
|
32
|
-
const sensitiveKeys = ['token', 'password', 'secret', 'key', 'auth', 'credential'];
|
|
33
|
-
const sanitized = { ...data };
|
|
34
|
-
for (const key of Object.keys(sanitized)) {
|
|
35
|
-
const lowerKey = key.toLowerCase();
|
|
36
|
-
if (sensitiveKeys.some(sk => lowerKey.includes(sk))) {
|
|
37
|
-
sanitized[key] = '[REDACTED]';
|
|
38
|
-
}
|
|
39
|
-
else if (typeof sanitized[key] === 'object') {
|
|
40
|
-
sanitized[key] = this.sanitizeData(sanitized[key]);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return sanitized;
|
|
44
|
-
}
|
|
45
|
-
formatMessage(level, message, data, tool) {
|
|
46
|
-
const timestamp = new Date().toISOString();
|
|
47
|
-
const levelName = LogLevel[level];
|
|
48
|
-
const toolInfo = tool ? `[${tool}] ` : '';
|
|
49
|
-
const dataStr = data ? ` ${JSON.stringify(this.sanitizeData(data))}` : '';
|
|
50
|
-
return `[${timestamp}] ${levelName} ${toolInfo}${message}${dataStr}`;
|
|
51
|
-
}
|
|
52
|
-
addLog(entry) {
|
|
53
|
-
this.logs.push(entry);
|
|
54
|
-
// Rotação automática
|
|
55
|
-
if (this.logs.length > this.maxEntries) {
|
|
56
|
-
this.logs = this.logs.slice(-this.maxEntries);
|
|
57
|
-
}
|
|
58
|
-
// Log para stderr em modo debug
|
|
59
|
-
if (this.logLevel >= LogLevel.DEBUG || entry.level <= LogLevel.WARN) {
|
|
60
|
-
console.error(this.formatMessage(entry.level, entry.message, entry.data, entry.tool));
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
error(message, data, tool) {
|
|
64
|
-
if (this.logLevel >= LogLevel.ERROR) {
|
|
65
|
-
this.addLog({
|
|
66
|
-
timestamp: new Date().toISOString(),
|
|
67
|
-
level: LogLevel.ERROR,
|
|
68
|
-
message,
|
|
69
|
-
data,
|
|
70
|
-
tool,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
warn(message, data, tool) {
|
|
75
|
-
if (this.logLevel >= LogLevel.WARN) {
|
|
76
|
-
this.addLog({
|
|
77
|
-
timestamp: new Date().toISOString(),
|
|
78
|
-
level: LogLevel.WARN,
|
|
79
|
-
message,
|
|
80
|
-
data,
|
|
81
|
-
tool,
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
info(message, data, tool) {
|
|
86
|
-
if (this.logLevel >= LogLevel.INFO) {
|
|
87
|
-
this.addLog({
|
|
88
|
-
timestamp: new Date().toISOString(),
|
|
89
|
-
level: LogLevel.INFO,
|
|
90
|
-
message,
|
|
91
|
-
data,
|
|
92
|
-
tool,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
debug(message, data, tool) {
|
|
97
|
-
if (this.logLevel >= LogLevel.DEBUG) {
|
|
98
|
-
this.addLog({
|
|
99
|
-
timestamp: new Date().toISOString(),
|
|
100
|
-
level: LogLevel.DEBUG,
|
|
101
|
-
message,
|
|
102
|
-
data,
|
|
103
|
-
tool,
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
getRecentLogs(level, limit = 100) {
|
|
108
|
-
let filtered = this.logs;
|
|
109
|
-
if (level !== undefined) {
|
|
110
|
-
filtered = filtered.filter(entry => entry.level <= level);
|
|
111
|
-
}
|
|
112
|
-
return filtered.slice(-limit);
|
|
113
|
-
}
|
|
114
|
-
clearLogs() {
|
|
115
|
-
this.logs = [];
|
|
116
|
-
}
|
|
117
|
-
setLogLevel(level) {
|
|
118
|
-
this.logLevel = level;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Helper functions para logging em diferentes contextos
|
|
123
|
-
*/
|
|
124
|
-
export function logToolExecution(toolName, args, result, error) {
|
|
125
|
-
const logger = Logger.getInstance();
|
|
126
|
-
if (error) {
|
|
127
|
-
logger.error(`Tool execution failed: ${toolName}`, { args, error: error.message }, toolName);
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
logger.info(`Tool executed successfully: ${toolName}`, { args, result: result ? 'success' : 'no result' }, toolName);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
export function logSecurityEvent(event, details) {
|
|
134
|
-
const logger = Logger.getInstance();
|
|
135
|
-
logger.warn(`Security event: ${event}`, details, 'SECURITY');
|
|
136
|
-
}
|
|
137
|
-
export function logPerformanceMetric(operation, duration, details) {
|
|
138
|
-
const logger = Logger.getInstance();
|
|
139
|
-
logger.debug(`Performance: ${operation} took ${duration}ms`, details, 'PERFORMANCE');
|
|
140
|
-
}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sistema de rate limiting para proteção contra abuso
|
|
3
|
-
* Implementa algoritmo token bucket com diferentes limites por tipo de operação
|
|
4
|
-
*/
|
|
5
|
-
export interface RateLimitConfig {
|
|
6
|
-
maxRequests: number;
|
|
7
|
-
windowMs: number;
|
|
8
|
-
burst?: number;
|
|
9
|
-
keyGenerator?: (toolName: string, args: any) => string;
|
|
10
|
-
}
|
|
11
|
-
export interface RateLimitEntry {
|
|
12
|
-
tokens: number;
|
|
13
|
-
lastRefill: number;
|
|
14
|
-
requestCount: number;
|
|
15
|
-
windowStart: number;
|
|
16
|
-
}
|
|
17
|
-
export declare class RateLimiter {
|
|
18
|
-
private static instance;
|
|
19
|
-
private limits;
|
|
20
|
-
private configs;
|
|
21
|
-
private cleanupInterval;
|
|
22
|
-
private constructor();
|
|
23
|
-
static getInstance(): RateLimiter;
|
|
24
|
-
/**
|
|
25
|
-
* Configurações padrão por tipo de operação
|
|
26
|
-
*/
|
|
27
|
-
private setupDefaultConfigs;
|
|
28
|
-
/**
|
|
29
|
-
* Classifica operação por tipo
|
|
30
|
-
*/
|
|
31
|
-
private classifyOperation;
|
|
32
|
-
/**
|
|
33
|
-
* Gera chave única para rate limiting
|
|
34
|
-
*/
|
|
35
|
-
private generateKey;
|
|
36
|
-
/**
|
|
37
|
-
* Verifica se request está dentro dos limites
|
|
38
|
-
*/
|
|
39
|
-
checkLimit(toolName: string, args: any): {
|
|
40
|
-
allowed: boolean;
|
|
41
|
-
remaining: number;
|
|
42
|
-
resetTime: number;
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* Configura limites personalizados para ferramenta específica
|
|
46
|
-
*/
|
|
47
|
-
setCustomLimit(toolName: string, config: RateLimitConfig): void;
|
|
48
|
-
/**
|
|
49
|
-
* Remove limites para ferramenta específica
|
|
50
|
-
*/
|
|
51
|
-
removeCustomLimit(toolName: string): void;
|
|
52
|
-
/**
|
|
53
|
-
* Obtém estatísticas de uso
|
|
54
|
-
*/
|
|
55
|
-
getStats(): {
|
|
56
|
-
totalKeys: number;
|
|
57
|
-
configs: Map<string, RateLimitConfig>;
|
|
58
|
-
activeLimits: Array<{
|
|
59
|
-
key: string;
|
|
60
|
-
entry: RateLimitEntry;
|
|
61
|
-
config: RateLimitConfig;
|
|
62
|
-
}>;
|
|
63
|
-
};
|
|
64
|
-
/**
|
|
65
|
-
* Limpa entradas antigas
|
|
66
|
-
*/
|
|
67
|
-
private startCleanup;
|
|
68
|
-
/**
|
|
69
|
-
* Para o cleanup automático
|
|
70
|
-
*/
|
|
71
|
-
stopCleanup(): void;
|
|
72
|
-
/**
|
|
73
|
-
* Limpa todos os limites
|
|
74
|
-
*/
|
|
75
|
-
clear(): void;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Middleware de rate limiting para integração com ferramentas
|
|
79
|
-
*/
|
|
80
|
-
export declare function withRateLimit(toolName: string, customConfig?: RateLimitConfig): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
81
|
-
/**
|
|
82
|
-
* Helper functions para rate limiting
|
|
83
|
-
*/
|
|
84
|
-
export declare const rateLimitHelpers: {
|
|
85
|
-
/**
|
|
86
|
-
* Verifica limite antes de executar operação
|
|
87
|
-
*/
|
|
88
|
-
checkLimit(toolName: string, args: any): {
|
|
89
|
-
allowed: boolean;
|
|
90
|
-
remaining: number;
|
|
91
|
-
resetTime: number;
|
|
92
|
-
};
|
|
93
|
-
/**
|
|
94
|
-
* Configura limite personalizado
|
|
95
|
-
*/
|
|
96
|
-
setCustomLimit(toolName: string, maxRequests: number, windowMs: number, burst?: number): void;
|
|
97
|
-
/**
|
|
98
|
-
* Obtém estatísticas
|
|
99
|
-
*/
|
|
100
|
-
getStats(): {
|
|
101
|
-
totalKeys: number;
|
|
102
|
-
configs: Map<string, RateLimitConfig>;
|
|
103
|
-
activeLimits: Array<{
|
|
104
|
-
key: string;
|
|
105
|
-
entry: RateLimitEntry;
|
|
106
|
-
config: RateLimitConfig;
|
|
107
|
-
}>;
|
|
108
|
-
};
|
|
109
|
-
/**
|
|
110
|
-
* Limpa todos os limites
|
|
111
|
-
*/
|
|
112
|
-
clear(): void;
|
|
113
|
-
};
|
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sistema de rate limiting para proteção contra abuso
|
|
3
|
-
* Implementa algoritmo token bucket com diferentes limites por tipo de operação
|
|
4
|
-
*/
|
|
5
|
-
export class RateLimiter {
|
|
6
|
-
constructor() {
|
|
7
|
-
this.cleanupInterval = null;
|
|
8
|
-
this.limits = new Map();
|
|
9
|
-
this.configs = new Map();
|
|
10
|
-
this.setupDefaultConfigs();
|
|
11
|
-
this.startCleanup();
|
|
12
|
-
}
|
|
13
|
-
static getInstance() {
|
|
14
|
-
if (!RateLimiter.instance) {
|
|
15
|
-
RateLimiter.instance = new RateLimiter();
|
|
16
|
-
}
|
|
17
|
-
return RateLimiter.instance;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Configurações padrão por tipo de operação
|
|
21
|
-
*/
|
|
22
|
-
setupDefaultConfigs() {
|
|
23
|
-
// Operações de leitura - limite mais alto
|
|
24
|
-
this.configs.set('read', {
|
|
25
|
-
maxRequests: 100,
|
|
26
|
-
windowMs: 60000, // 1 minuto
|
|
27
|
-
burst: 10,
|
|
28
|
-
});
|
|
29
|
-
// Operações de escrita - limite médio
|
|
30
|
-
this.configs.set('write', {
|
|
31
|
-
maxRequests: 30,
|
|
32
|
-
windowMs: 60000, // 1 minuto
|
|
33
|
-
burst: 5,
|
|
34
|
-
});
|
|
35
|
-
// Operações destrutivas - limite baixo
|
|
36
|
-
this.configs.set('destructive', {
|
|
37
|
-
maxRequests: 10,
|
|
38
|
-
windowMs: 60000, // 1 minuto
|
|
39
|
-
burst: 2,
|
|
40
|
-
});
|
|
41
|
-
// Operações de upload - limite especial
|
|
42
|
-
this.configs.set('upload', {
|
|
43
|
-
maxRequests: 20,
|
|
44
|
-
windowMs: 60000, // 1 minuto
|
|
45
|
-
burst: 3,
|
|
46
|
-
});
|
|
47
|
-
// Default para operações não categorizadas
|
|
48
|
-
this.configs.set('default', {
|
|
49
|
-
maxRequests: 50,
|
|
50
|
-
windowMs: 60000, // 1 minuto
|
|
51
|
-
burst: 5,
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Classifica operação por tipo
|
|
56
|
-
*/
|
|
57
|
-
classifyOperation(toolName) {
|
|
58
|
-
const destructiveOps = ['reset', 'force', 'delete', 'destroy', 'clean'];
|
|
59
|
-
const uploadOps = ['upload', 'push', 'commit'];
|
|
60
|
-
const writeOps = ['create', 'update', 'edit', 'modify', 'add', 'remove'];
|
|
61
|
-
const toolLower = toolName.toLowerCase();
|
|
62
|
-
if (destructiveOps.some(op => toolLower.includes(op))) {
|
|
63
|
-
return 'destructive';
|
|
64
|
-
}
|
|
65
|
-
if (uploadOps.some(op => toolLower.includes(op))) {
|
|
66
|
-
return 'upload';
|
|
67
|
-
}
|
|
68
|
-
if (writeOps.some(op => toolLower.includes(op))) {
|
|
69
|
-
return 'write';
|
|
70
|
-
}
|
|
71
|
-
if (toolLower.includes('read') || toolLower.includes('get') || toolLower.includes('list')) {
|
|
72
|
-
return 'read';
|
|
73
|
-
}
|
|
74
|
-
return 'default';
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Gera chave única para rate limiting
|
|
78
|
-
*/
|
|
79
|
-
generateKey(toolName, args) {
|
|
80
|
-
// Usar projectPath como identificador principal, fallback para toolName
|
|
81
|
-
const projectPath = args?.projectPath || 'global';
|
|
82
|
-
const operationType = this.classifyOperation(toolName);
|
|
83
|
-
return `rate_limit:${operationType}:${projectPath}:${toolName}`;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Verifica se request está dentro dos limites
|
|
87
|
-
*/
|
|
88
|
-
checkLimit(toolName, args) {
|
|
89
|
-
const operationType = this.classifyOperation(toolName);
|
|
90
|
-
const config = this.configs.get(operationType) || this.configs.get('default');
|
|
91
|
-
const key = config.keyGenerator ? config.keyGenerator(toolName, args) : this.generateKey(toolName, args);
|
|
92
|
-
const now = Date.now();
|
|
93
|
-
let entry = this.limits.get(key);
|
|
94
|
-
if (!entry) {
|
|
95
|
-
entry = {
|
|
96
|
-
tokens: config.maxRequests,
|
|
97
|
-
lastRefill: now,
|
|
98
|
-
requestCount: 0,
|
|
99
|
-
windowStart: now,
|
|
100
|
-
};
|
|
101
|
-
this.limits.set(key, entry);
|
|
102
|
-
}
|
|
103
|
-
// Refill tokens baseado no tempo decorrido
|
|
104
|
-
const timePassed = now - entry.lastRefill;
|
|
105
|
-
const tokensToAdd = Math.floor(timePassed / (config.windowMs / config.maxRequests));
|
|
106
|
-
if (tokensToAdd > 0) {
|
|
107
|
-
entry.tokens = Math.min(config.maxRequests, entry.tokens + tokensToAdd);
|
|
108
|
-
entry.lastRefill = now;
|
|
109
|
-
}
|
|
110
|
-
// Verificar janela de tempo
|
|
111
|
-
if (now - entry.windowStart > config.windowMs) {
|
|
112
|
-
entry.requestCount = 0;
|
|
113
|
-
entry.windowStart = now;
|
|
114
|
-
}
|
|
115
|
-
// Verificar burst limit
|
|
116
|
-
const burstLimit = config.burst || config.maxRequests;
|
|
117
|
-
if (entry.requestCount >= burstLimit) {
|
|
118
|
-
return {
|
|
119
|
-
allowed: false,
|
|
120
|
-
remaining: 0,
|
|
121
|
-
resetTime: entry.windowStart + config.windowMs,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
// Verificar token bucket
|
|
125
|
-
if (entry.tokens <= 0) {
|
|
126
|
-
return {
|
|
127
|
-
allowed: false,
|
|
128
|
-
remaining: 0,
|
|
129
|
-
resetTime: entry.lastRefill + (config.windowMs / config.maxRequests),
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
// Consumir token e registrar request
|
|
133
|
-
entry.tokens--;
|
|
134
|
-
entry.requestCount++;
|
|
135
|
-
return {
|
|
136
|
-
allowed: true,
|
|
137
|
-
remaining: entry.tokens,
|
|
138
|
-
resetTime: entry.lastRefill + (config.windowMs / config.maxRequests),
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Configura limites personalizados para ferramenta específica
|
|
143
|
-
*/
|
|
144
|
-
setCustomLimit(toolName, config) {
|
|
145
|
-
this.configs.set(toolName, config);
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Remove limites para ferramenta específica
|
|
149
|
-
*/
|
|
150
|
-
removeCustomLimit(toolName) {
|
|
151
|
-
this.configs.delete(toolName);
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Obtém estatísticas de uso
|
|
155
|
-
*/
|
|
156
|
-
getStats() {
|
|
157
|
-
const activeLimits = [];
|
|
158
|
-
for (const [key, entry] of this.limits.entries()) {
|
|
159
|
-
const operationType = key.split(':')[1] || 'default';
|
|
160
|
-
const config = this.configs.get(operationType) || this.configs.get('default');
|
|
161
|
-
activeLimits.push({ key, entry, config });
|
|
162
|
-
}
|
|
163
|
-
return {
|
|
164
|
-
totalKeys: this.limits.size,
|
|
165
|
-
configs: new Map(this.configs),
|
|
166
|
-
activeLimits,
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Limpa entradas antigas
|
|
171
|
-
*/
|
|
172
|
-
startCleanup() {
|
|
173
|
-
// Limpar a cada 5 minutos
|
|
174
|
-
this.cleanupInterval = setInterval(() => {
|
|
175
|
-
const now = Date.now();
|
|
176
|
-
const maxAge = 10 * 60 * 1000; // 10 minutos
|
|
177
|
-
for (const [key, entry] of this.limits.entries()) {
|
|
178
|
-
if (now - entry.lastRefill > maxAge) {
|
|
179
|
-
this.limits.delete(key);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}, 5 * 60 * 1000);
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Para o cleanup automático
|
|
186
|
-
*/
|
|
187
|
-
stopCleanup() {
|
|
188
|
-
if (this.cleanupInterval) {
|
|
189
|
-
clearInterval(this.cleanupInterval);
|
|
190
|
-
this.cleanupInterval = null;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Limpa todos os limites
|
|
195
|
-
*/
|
|
196
|
-
clear() {
|
|
197
|
-
this.limits.clear();
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Middleware de rate limiting para integração com ferramentas
|
|
202
|
-
*/
|
|
203
|
-
export function withRateLimit(toolName, customConfig) {
|
|
204
|
-
const rateLimiter = RateLimiter.getInstance();
|
|
205
|
-
if (customConfig) {
|
|
206
|
-
rateLimiter.setCustomLimit(toolName, customConfig);
|
|
207
|
-
}
|
|
208
|
-
return function (target, propertyKey, descriptor) {
|
|
209
|
-
const originalMethod = descriptor.value;
|
|
210
|
-
descriptor.value = async function (...args) {
|
|
211
|
-
const argsObj = args[0] || {};
|
|
212
|
-
const limitResult = rateLimiter.checkLimit(toolName, argsObj);
|
|
213
|
-
if (!limitResult.allowed) {
|
|
214
|
-
const error = new Error(`Rate limit exceeded for ${toolName}. Try again in ${Math.ceil((limitResult.resetTime - Date.now()) / 1000)}s`);
|
|
215
|
-
error.code = 'RATE_LIMIT_EXCEEDED';
|
|
216
|
-
error.resetTime = limitResult.resetTime;
|
|
217
|
-
error.remaining = limitResult.remaining;
|
|
218
|
-
throw error;
|
|
219
|
-
}
|
|
220
|
-
return originalMethod.apply(this, args);
|
|
221
|
-
};
|
|
222
|
-
return descriptor;
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Helper functions para rate limiting
|
|
227
|
-
*/
|
|
228
|
-
export const rateLimitHelpers = {
|
|
229
|
-
/**
|
|
230
|
-
* Verifica limite antes de executar operação
|
|
231
|
-
*/
|
|
232
|
-
checkLimit(toolName, args) {
|
|
233
|
-
const rateLimiter = RateLimiter.getInstance();
|
|
234
|
-
return rateLimiter.checkLimit(toolName, args);
|
|
235
|
-
},
|
|
236
|
-
/**
|
|
237
|
-
* Configura limite personalizado
|
|
238
|
-
*/
|
|
239
|
-
setCustomLimit(toolName, maxRequests, windowMs, burst) {
|
|
240
|
-
const rateLimiter = RateLimiter.getInstance();
|
|
241
|
-
rateLimiter.setCustomLimit(toolName, { maxRequests, windowMs, burst });
|
|
242
|
-
},
|
|
243
|
-
/**
|
|
244
|
-
* Obtém estatísticas
|
|
245
|
-
*/
|
|
246
|
-
getStats() {
|
|
247
|
-
const rateLimiter = RateLimiter.getInstance();
|
|
248
|
-
return rateLimiter.getStats();
|
|
249
|
-
},
|
|
250
|
-
/**
|
|
251
|
-
* Limpa todos os limites
|
|
252
|
-
*/
|
|
253
|
-
clear() {
|
|
254
|
-
const rateLimiter = RateLimiter.getInstance();
|
|
255
|
-
rateLimiter.clear();
|
|
256
|
-
},
|
|
257
|
-
};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helper functions to extract repository information automatically
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Extract repository name from project path
|
|
6
|
-
* Normalizes: spaces to hyphens, lowercase, keeps alphanumeric and hyphens/underscores
|
|
7
|
-
*/
|
|
8
|
-
export declare function getRepoNameFromPath(projectPath: string): string;
|
|
9
|
-
/**
|
|
10
|
-
* Get GitHub owner from environment
|
|
11
|
-
*/
|
|
12
|
-
export declare function getGitHubOwner(): string | undefined;
|
|
13
|
-
/**
|
|
14
|
-
* Get Gitea owner from environment
|
|
15
|
-
*/
|
|
16
|
-
export declare function getGiteaOwner(): string | undefined;
|
|
17
|
-
/**
|
|
18
|
-
* Get Gitea base URL from environment
|
|
19
|
-
*/
|
|
20
|
-
export declare function getGiteaUrl(): string | undefined;
|
|
21
|
-
/**
|
|
22
|
-
* Build GitHub repository URL
|
|
23
|
-
*/
|
|
24
|
-
export declare function buildGitHubUrl(owner: string, repo: string): string;
|
|
25
|
-
/**
|
|
26
|
-
* Build Gitea repository URL with credentials
|
|
27
|
-
*/
|
|
28
|
-
export declare function buildGiteaUrl(owner: string, repo: string): string;
|
|
29
|
-
/**
|
|
30
|
-
* Get repository info from project path and environment
|
|
31
|
-
*/
|
|
32
|
-
export declare function getRepoInfo(projectPath: string): {
|
|
33
|
-
repoName: string;
|
|
34
|
-
githubOwner: string | undefined;
|
|
35
|
-
giteaOwner: string | undefined;
|
|
36
|
-
githubUrl: string | undefined;
|
|
37
|
-
giteaUrl: string | undefined;
|
|
38
|
-
};
|
|
39
|
-
/**
|
|
40
|
-
* Normalize parameters from different IDEs/agents
|
|
41
|
-
* Maps common Git commands to tool actions
|
|
42
|
-
* Handles both 'action' and 'command' parameters
|
|
43
|
-
*/
|
|
44
|
-
export declare function normalizeToolParams(params: Record<string, any>): Record<string, any>;
|