@trentapps/manager-protocol 1.1.3 → 1.2.1
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 +164 -17
- package/dist/analyzers/CSSAnalyzer.d.ts +180 -8
- package/dist/analyzers/CSSAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/CSSAnalyzer.js +561 -105
- package/dist/analyzers/CSSAnalyzer.js.map +1 -1
- package/dist/config/dashboard.d.ts +55 -0
- package/dist/config/dashboard.d.ts.map +1 -0
- package/dist/config/dashboard.js +103 -0
- package/dist/config/dashboard.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +7 -0
- package/dist/config/index.js.map +1 -0
- package/dist/dashboard/httpDashboard.d.ts +100 -0
- package/dist/dashboard/httpDashboard.d.ts.map +1 -0
- package/dist/dashboard/httpDashboard.js +1276 -0
- package/dist/dashboard/httpDashboard.js.map +1 -0
- package/dist/dashboard/index.d.ts +6 -0
- package/dist/dashboard/index.d.ts.map +1 -0
- package/dist/dashboard/index.js +7 -0
- package/dist/dashboard/index.js.map +1 -0
- package/dist/engine/AuditLogger.d.ts +370 -2
- package/dist/engine/AuditLogger.d.ts.map +1 -1
- package/dist/engine/AuditLogger.js +1064 -24
- package/dist/engine/AuditLogger.js.map +1 -1
- package/dist/engine/GitHubClient.d.ts +183 -0
- package/dist/engine/GitHubClient.d.ts.map +1 -0
- package/dist/engine/GitHubClient.js +411 -0
- package/dist/engine/GitHubClient.js.map +1 -0
- package/dist/engine/RateLimiter.d.ts +5 -3
- package/dist/engine/RateLimiter.d.ts.map +1 -1
- package/dist/engine/RateLimiter.js +49 -72
- package/dist/engine/RateLimiter.js.map +1 -1
- package/dist/engine/RuleDependencyAnalyzer.d.ts +73 -0
- package/dist/engine/RuleDependencyAnalyzer.d.ts.map +1 -0
- package/dist/engine/RuleDependencyAnalyzer.js +475 -0
- package/dist/engine/RuleDependencyAnalyzer.js.map +1 -0
- package/dist/engine/RulesEngine.d.ts +102 -3
- package/dist/engine/RulesEngine.d.ts.map +1 -1
- package/dist/engine/RulesEngine.js +326 -21
- package/dist/engine/RulesEngine.js.map +1 -1
- package/dist/engine/TaskManager.d.ts +10 -14
- package/dist/engine/TaskManager.d.ts.map +1 -1
- package/dist/engine/TaskManager.js +169 -197
- package/dist/engine/TaskManager.js.map +1 -1
- package/dist/engine/index.d.ts +3 -0
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +5 -0
- package/dist/engine/index.js.map +1 -1
- package/dist/rules/azure.d.ts.map +1 -1
- package/dist/rules/azure.js +12 -14
- package/dist/rules/azure.js.map +1 -1
- package/dist/rules/compliance.d.ts.map +1 -1
- package/dist/rules/compliance.js +23 -41
- package/dist/rules/compliance.js.map +1 -1
- package/dist/rules/condition-optimizer.d.ts +151 -0
- package/dist/rules/condition-optimizer.d.ts.map +1 -0
- package/dist/rules/condition-optimizer.js +479 -0
- package/dist/rules/condition-optimizer.js.map +1 -0
- package/dist/rules/css.d.ts.map +1 -1
- package/dist/rules/css.js +538 -0
- package/dist/rules/css.js.map +1 -1
- package/dist/rules/field-standards.d.ts +1172 -0
- package/dist/rules/field-standards.d.ts.map +1 -0
- package/dist/rules/field-standards.js +908 -0
- package/dist/rules/field-standards.js.map +1 -0
- package/dist/rules/flask.d.ts.map +1 -1
- package/dist/rules/flask.js +18 -31
- package/dist/rules/flask.js.map +1 -1
- package/dist/rules/index.d.ts +220 -0
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +155 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/ml-ai.d.ts.map +1 -1
- package/dist/rules/ml-ai.js +11 -13
- package/dist/rules/ml-ai.js.map +1 -1
- package/dist/rules/patterns.d.ts +568 -0
- package/dist/rules/patterns.d.ts.map +1 -0
- package/dist/rules/patterns.js +1359 -0
- package/dist/rules/patterns.js.map +1 -0
- package/dist/rules/security.d.ts.map +1 -1
- package/dist/rules/security.js +580 -19
- package/dist/rules/security.js.map +1 -1
- package/dist/rules/shared-patterns.d.ts +268 -0
- package/dist/rules/shared-patterns.d.ts.map +1 -0
- package/dist/rules/shared-patterns.js +556 -0
- package/dist/rules/shared-patterns.js.map +1 -0
- package/dist/rules/storage.d.ts +8 -2
- package/dist/rules/storage.d.ts.map +1 -1
- package/dist/rules/storage.js +541 -3
- package/dist/rules/storage.js.map +1 -1
- package/dist/rules/stripe.d.ts.map +1 -1
- package/dist/rules/stripe.js +19 -26
- package/dist/rules/stripe.js.map +1 -1
- package/dist/rules/websocket.d.ts.map +1 -1
- package/dist/rules/websocket.js +32 -40
- package/dist/rules/websocket.js.map +1 -1
- package/dist/supervisor/AgentSupervisor.d.ts +52 -0
- package/dist/supervisor/AgentSupervisor.d.ts.map +1 -1
- package/dist/supervisor/AgentSupervisor.js +120 -1
- package/dist/supervisor/AgentSupervisor.js.map +1 -1
- package/dist/supervisor/ManagedServerRegistry.d.ts +139 -2
- package/dist/supervisor/ManagedServerRegistry.d.ts.map +1 -1
- package/dist/supervisor/ManagedServerRegistry.js +590 -6
- package/dist/supervisor/ManagedServerRegistry.js.map +1 -1
- package/dist/supervisor/ProjectTracker.d.ts +2 -1
- package/dist/supervisor/ProjectTracker.d.ts.map +1 -1
- package/dist/supervisor/ProjectTracker.js +5 -9
- package/dist/supervisor/ProjectTracker.js.map +1 -1
- package/dist/testing/index.d.ts +11 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +12 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/rule-tester.d.ts +217 -0
- package/dist/testing/rule-tester.d.ts.map +1 -0
- package/dist/testing/rule-tester.examples.d.ts +57 -0
- package/dist/testing/rule-tester.examples.d.ts.map +1 -0
- package/dist/testing/rule-tester.examples.js +375 -0
- package/dist/testing/rule-tester.examples.js.map +1 -0
- package/dist/testing/rule-tester.js +381 -0
- package/dist/testing/rule-tester.js.map +1 -0
- package/dist/testing/rule-validator.d.ts +141 -0
- package/dist/testing/rule-validator.d.ts.map +1 -0
- package/dist/testing/rule-validator.js +640 -0
- package/dist/testing/rule-validator.js.map +1 -0
- package/dist/types/index.d.ts +265 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +57 -2
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/rate-limiting.d.ts +268 -0
- package/dist/utils/rate-limiting.d.ts.map +1 -0
- package/dist/utils/rate-limiting.js +403 -0
- package/dist/utils/rate-limiting.js.map +1 -0
- package/dist/utils/shared.d.ts +306 -0
- package/dist/utils/shared.d.ts.map +1 -0
- package/dist/utils/shared.js +464 -0
- package/dist/utils/shared.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enterprise Agent Supervisor - GitHub Client
|
|
3
|
+
*
|
|
4
|
+
* Provides a clean wrapper around the GitHub API via Octokit.
|
|
5
|
+
* Used by TaskManager for GitHub Issues operations.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Singleton pattern for connection reuse
|
|
9
|
+
* - Automatic authentication via GITHUB_TOKEN
|
|
10
|
+
* - Repository auto-detection from git remote
|
|
11
|
+
* - Proper TypeScript types
|
|
12
|
+
* - Structured error handling
|
|
13
|
+
*/
|
|
14
|
+
import { Octokit } from '@octokit/rest';
|
|
15
|
+
import { exec } from 'child_process';
|
|
16
|
+
import { promisify } from 'util';
|
|
17
|
+
const execAsync = promisify(exec);
|
|
18
|
+
/**
|
|
19
|
+
* GitHub API client using Octokit
|
|
20
|
+
*/
|
|
21
|
+
export class GitHubClient {
|
|
22
|
+
static instance = null;
|
|
23
|
+
octokit;
|
|
24
|
+
cachedRepo = null;
|
|
25
|
+
authenticated = false;
|
|
26
|
+
constructor() {
|
|
27
|
+
const token = process.env.GITHUB_TOKEN;
|
|
28
|
+
if (!token) {
|
|
29
|
+
console.warn('[GitHubClient] GITHUB_TOKEN not set - some operations may fail');
|
|
30
|
+
}
|
|
31
|
+
this.octokit = new Octokit({
|
|
32
|
+
auth: token,
|
|
33
|
+
userAgent: 'enterprise-agent-supervisor/1.1.3',
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get singleton instance
|
|
38
|
+
*/
|
|
39
|
+
static getInstance() {
|
|
40
|
+
if (!GitHubClient.instance) {
|
|
41
|
+
GitHubClient.instance = new GitHubClient();
|
|
42
|
+
}
|
|
43
|
+
return GitHubClient.instance;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Reset singleton instance (for testing)
|
|
47
|
+
*/
|
|
48
|
+
static resetInstance() {
|
|
49
|
+
GitHubClient.instance = null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Verify authentication and get current user
|
|
53
|
+
*/
|
|
54
|
+
async verifyAuth() {
|
|
55
|
+
if (this.authenticated) {
|
|
56
|
+
return { ok: true };
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
const { data } = await this.octokit.users.getAuthenticated();
|
|
60
|
+
this.authenticated = true;
|
|
61
|
+
return { ok: true, user: data.login };
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
const err = error;
|
|
65
|
+
if (err.status === 401) {
|
|
66
|
+
return { ok: false, error: 'GitHub authentication failed. Set GITHUB_TOKEN environment variable.' };
|
|
67
|
+
}
|
|
68
|
+
return { ok: false, error: err.message || 'Unknown authentication error' };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Parse owner/repo string into components
|
|
73
|
+
*/
|
|
74
|
+
parseRepo(repoString) {
|
|
75
|
+
const parts = repoString.split('/');
|
|
76
|
+
if (parts.length !== 2) {
|
|
77
|
+
throw new Error(`Invalid repository format: ${repoString}. Expected "owner/repo".`);
|
|
78
|
+
}
|
|
79
|
+
return { owner: parts[0], repo: parts[1] };
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get current repository from git remote
|
|
83
|
+
*/
|
|
84
|
+
async getCurrentRepo() {
|
|
85
|
+
if (this.cachedRepo) {
|
|
86
|
+
return this.cachedRepo;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
// Try to get repo from git remote
|
|
90
|
+
const { stdout } = await execAsync('git remote get-url origin 2>/dev/null');
|
|
91
|
+
const url = stdout.trim();
|
|
92
|
+
// Parse various git remote URL formats:
|
|
93
|
+
// https://github.com/owner/repo.git
|
|
94
|
+
// git@github.com:owner/repo.git
|
|
95
|
+
// https://github.com/owner/repo
|
|
96
|
+
let match = url.match(/github\.com[:/]([^/]+)\/([^/.]+)/);
|
|
97
|
+
if (match) {
|
|
98
|
+
this.cachedRepo = { owner: match[1], repo: match[2] };
|
|
99
|
+
return this.cachedRepo;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// Git command failed
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Handle API errors consistently
|
|
109
|
+
*/
|
|
110
|
+
handleError(error, operation) {
|
|
111
|
+
const err = error;
|
|
112
|
+
if (err.status === 401) {
|
|
113
|
+
throw new Error(`Authentication failed for ${operation}. Check GITHUB_TOKEN.`);
|
|
114
|
+
}
|
|
115
|
+
if (err.status === 403) {
|
|
116
|
+
throw new Error(`Permission denied for ${operation}. Check repository access.`);
|
|
117
|
+
}
|
|
118
|
+
if (err.status === 404) {
|
|
119
|
+
throw new Error(`Not found during ${operation}. Check repository/issue exists.`);
|
|
120
|
+
}
|
|
121
|
+
if (err.status === 422) {
|
|
122
|
+
throw new Error(`Validation failed for ${operation}: ${err.message}`);
|
|
123
|
+
}
|
|
124
|
+
throw new Error(`GitHub API error during ${operation}: ${err.message || 'Unknown error'}`);
|
|
125
|
+
}
|
|
126
|
+
// ============================================================================
|
|
127
|
+
// ISSUE OPERATIONS
|
|
128
|
+
// ============================================================================
|
|
129
|
+
/**
|
|
130
|
+
* Create a new issue
|
|
131
|
+
*/
|
|
132
|
+
async createIssue(params) {
|
|
133
|
+
try {
|
|
134
|
+
const { data } = await this.octokit.issues.create({
|
|
135
|
+
owner: params.owner,
|
|
136
|
+
repo: params.repo,
|
|
137
|
+
title: params.title,
|
|
138
|
+
body: params.body,
|
|
139
|
+
labels: params.labels,
|
|
140
|
+
assignees: params.assignees,
|
|
141
|
+
milestone: params.milestone,
|
|
142
|
+
});
|
|
143
|
+
return this.normalizeIssue(data);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
this.handleError(error, 'createIssue');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get a single issue by number
|
|
151
|
+
*/
|
|
152
|
+
async getIssue(owner, repo, issueNumber) {
|
|
153
|
+
try {
|
|
154
|
+
const { data } = await this.octokit.issues.get({
|
|
155
|
+
owner,
|
|
156
|
+
repo,
|
|
157
|
+
issue_number: issueNumber,
|
|
158
|
+
});
|
|
159
|
+
return this.normalizeIssue(data);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
this.handleError(error, 'getIssue');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* List issues for a repository
|
|
167
|
+
*/
|
|
168
|
+
async listIssues(params) {
|
|
169
|
+
try {
|
|
170
|
+
const { data } = await this.octokit.issues.listForRepo({
|
|
171
|
+
owner: params.owner,
|
|
172
|
+
repo: params.repo,
|
|
173
|
+
state: params.state || 'all',
|
|
174
|
+
labels: params.labels,
|
|
175
|
+
assignee: params.assignee,
|
|
176
|
+
per_page: params.per_page || 100,
|
|
177
|
+
page: params.page || 1,
|
|
178
|
+
});
|
|
179
|
+
// Filter out pull requests (GitHub API returns PRs in issues endpoint)
|
|
180
|
+
return data
|
|
181
|
+
.filter((issue) => !('pull_request' in issue))
|
|
182
|
+
.map((issue) => this.normalizeIssue(issue));
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
this.handleError(error, 'listIssues');
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Update an existing issue
|
|
190
|
+
*/
|
|
191
|
+
async updateIssue(params) {
|
|
192
|
+
try {
|
|
193
|
+
const { data } = await this.octokit.issues.update({
|
|
194
|
+
owner: params.owner,
|
|
195
|
+
repo: params.repo,
|
|
196
|
+
issue_number: params.issue_number,
|
|
197
|
+
title: params.title,
|
|
198
|
+
body: params.body,
|
|
199
|
+
state: params.state,
|
|
200
|
+
state_reason: params.state_reason,
|
|
201
|
+
labels: params.labels,
|
|
202
|
+
assignees: params.assignees,
|
|
203
|
+
milestone: params.milestone,
|
|
204
|
+
});
|
|
205
|
+
return this.normalizeIssue(data);
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
this.handleError(error, 'updateIssue');
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Close an issue
|
|
213
|
+
*/
|
|
214
|
+
async closeIssue(owner, repo, issueNumber, reason = 'completed') {
|
|
215
|
+
return this.updateIssue({
|
|
216
|
+
owner,
|
|
217
|
+
repo,
|
|
218
|
+
issue_number: issueNumber,
|
|
219
|
+
state: 'closed',
|
|
220
|
+
state_reason: reason,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Reopen an issue
|
|
225
|
+
*/
|
|
226
|
+
async reopenIssue(owner, repo, issueNumber) {
|
|
227
|
+
return this.updateIssue({
|
|
228
|
+
owner,
|
|
229
|
+
repo,
|
|
230
|
+
issue_number: issueNumber,
|
|
231
|
+
state: 'open',
|
|
232
|
+
state_reason: 'reopened',
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
// ============================================================================
|
|
236
|
+
// COMMENT OPERATIONS
|
|
237
|
+
// ============================================================================
|
|
238
|
+
/**
|
|
239
|
+
* Add a comment to an issue
|
|
240
|
+
*/
|
|
241
|
+
async addComment(owner, repo, issueNumber, body) {
|
|
242
|
+
try {
|
|
243
|
+
await this.octokit.issues.createComment({
|
|
244
|
+
owner,
|
|
245
|
+
repo,
|
|
246
|
+
issue_number: issueNumber,
|
|
247
|
+
body,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
this.handleError(error, 'addComment');
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// ============================================================================
|
|
255
|
+
// LABEL OPERATIONS
|
|
256
|
+
// ============================================================================
|
|
257
|
+
/**
|
|
258
|
+
* Get a label
|
|
259
|
+
*/
|
|
260
|
+
async getLabel(owner, repo, labelName) {
|
|
261
|
+
try {
|
|
262
|
+
const { data } = await this.octokit.issues.getLabel({
|
|
263
|
+
owner,
|
|
264
|
+
repo,
|
|
265
|
+
name: labelName,
|
|
266
|
+
});
|
|
267
|
+
return {
|
|
268
|
+
name: data.name,
|
|
269
|
+
color: data.color,
|
|
270
|
+
description: data.description,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
const err = error;
|
|
275
|
+
if (err.status === 404) {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
this.handleError(error, 'getLabel');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Create a label
|
|
283
|
+
*/
|
|
284
|
+
async createLabel(owner, repo, name, color, description) {
|
|
285
|
+
try {
|
|
286
|
+
const { data } = await this.octokit.issues.createLabel({
|
|
287
|
+
owner,
|
|
288
|
+
repo,
|
|
289
|
+
name,
|
|
290
|
+
color,
|
|
291
|
+
description,
|
|
292
|
+
});
|
|
293
|
+
return {
|
|
294
|
+
name: data.name,
|
|
295
|
+
color: data.color,
|
|
296
|
+
description: data.description,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
const err = error;
|
|
301
|
+
// If label already exists, ignore the error
|
|
302
|
+
if (err.status === 422) {
|
|
303
|
+
return { name, color, description: description || null };
|
|
304
|
+
}
|
|
305
|
+
this.handleError(error, 'createLabel');
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Add labels to an issue
|
|
310
|
+
*/
|
|
311
|
+
async addLabels(owner, repo, issueNumber, labels) {
|
|
312
|
+
try {
|
|
313
|
+
await this.octokit.issues.addLabels({
|
|
314
|
+
owner,
|
|
315
|
+
repo,
|
|
316
|
+
issue_number: issueNumber,
|
|
317
|
+
labels,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
this.handleError(error, 'addLabels');
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Remove a label from an issue
|
|
326
|
+
*/
|
|
327
|
+
async removeLabel(owner, repo, issueNumber, label) {
|
|
328
|
+
try {
|
|
329
|
+
await this.octokit.issues.removeLabel({
|
|
330
|
+
owner,
|
|
331
|
+
repo,
|
|
332
|
+
issue_number: issueNumber,
|
|
333
|
+
name: label,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
const err = error;
|
|
338
|
+
// Ignore if label doesn't exist on the issue
|
|
339
|
+
if (err.status === 404) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
this.handleError(error, 'removeLabel');
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// ============================================================================
|
|
346
|
+
// SEARCH OPERATIONS
|
|
347
|
+
// ============================================================================
|
|
348
|
+
/**
|
|
349
|
+
* Search issues
|
|
350
|
+
*/
|
|
351
|
+
async searchIssues(params) {
|
|
352
|
+
try {
|
|
353
|
+
const { data } = await this.octokit.search.issuesAndPullRequests({
|
|
354
|
+
q: params.query + ' is:issue',
|
|
355
|
+
per_page: params.per_page || 50,
|
|
356
|
+
page: params.page || 1,
|
|
357
|
+
});
|
|
358
|
+
return data.items.map((item) => this.normalizeIssue(item));
|
|
359
|
+
}
|
|
360
|
+
catch (error) {
|
|
361
|
+
this.handleError(error, 'searchIssues');
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
// ============================================================================
|
|
365
|
+
// REPOSITORY OPERATIONS
|
|
366
|
+
// ============================================================================
|
|
367
|
+
/**
|
|
368
|
+
* List repositories for authenticated user
|
|
369
|
+
*/
|
|
370
|
+
async listRepos(limit = 20) {
|
|
371
|
+
try {
|
|
372
|
+
const { data } = await this.octokit.repos.listForAuthenticatedUser({
|
|
373
|
+
per_page: limit,
|
|
374
|
+
sort: 'pushed',
|
|
375
|
+
});
|
|
376
|
+
return data.map((repo) => ({ nameWithOwner: repo.full_name }));
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
this.handleError(error, 'listRepos');
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
// ============================================================================
|
|
383
|
+
// HELPERS
|
|
384
|
+
// ============================================================================
|
|
385
|
+
/**
|
|
386
|
+
* Normalize issue data to our interface
|
|
387
|
+
*/
|
|
388
|
+
normalizeIssue(data) {
|
|
389
|
+
return {
|
|
390
|
+
number: data.number,
|
|
391
|
+
title: data.title,
|
|
392
|
+
body: data.body,
|
|
393
|
+
state: data.state,
|
|
394
|
+
state_reason: data.state_reason,
|
|
395
|
+
labels: (data.labels || []).map((label) => ({
|
|
396
|
+
name: typeof label === 'string' ? label : label.name,
|
|
397
|
+
color: typeof label === 'string' ? undefined : label.color,
|
|
398
|
+
description: typeof label === 'string' ? null : label.description,
|
|
399
|
+
})),
|
|
400
|
+
assignees: data.assignees || [],
|
|
401
|
+
created_at: data.created_at,
|
|
402
|
+
updated_at: data.updated_at,
|
|
403
|
+
closed_at: data.closed_at,
|
|
404
|
+
html_url: data.html_url,
|
|
405
|
+
milestone: data.milestone ? { title: data.milestone.title } : null,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
// Export singleton getter for convenience
|
|
410
|
+
export const gitHubClient = GitHubClient.getInstance();
|
|
411
|
+
//# sourceMappingURL=GitHubClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitHubClient.js","sourceRoot":"","sources":["../../src/engine/GitHubClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Enterprise Agent Supervisor - Rate Limiter
|
|
3
3
|
*
|
|
4
4
|
* Token bucket rate limiting with multiple scopes and configurations.
|
|
5
|
+
* Uses extracted utilities from src/utils/rate-limiting.ts for
|
|
6
|
+
* bucket key building and sliding window logic.
|
|
5
7
|
*/
|
|
6
8
|
import type { RateLimitConfig, RateLimitState, ActionCategory } from '../types/index.js';
|
|
7
9
|
export declare class RateLimiter {
|
|
@@ -62,11 +64,11 @@ export declare class RateLimiter {
|
|
|
62
64
|
*/
|
|
63
65
|
clearBuckets(): void;
|
|
64
66
|
/**
|
|
65
|
-
*
|
|
67
|
+
* Convert params to BucketIdentifiers for the utility function
|
|
66
68
|
*/
|
|
67
|
-
private
|
|
69
|
+
private toIdentifiers;
|
|
68
70
|
/**
|
|
69
|
-
* Get or create a bucket
|
|
71
|
+
* Get or create a bucket with SlidingWindow
|
|
70
72
|
*/
|
|
71
73
|
private getOrCreateBucket;
|
|
72
74
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../src/engine/RateLimiter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../src/engine/RateLimiter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAWzF,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAA2C;IAC1D,OAAO,CAAC,OAAO,CAA2C;IAC1D,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,iBAAiB,CAAyB;IAElD;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAI5C;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI;IAMhD;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAItC;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,cAAc,CAAC,EAAE,cAAc,CAAC;QAChC,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,cAAc,CAAA;KAAE;IAyDlE;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,cAAc,CAAC,EAAE,cAAc,CAAC;QAChC,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,IAAI;IAqBR;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE;QACjC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,cAAc,GAAG,IAAI;IA8BzB;;OAEG;IACH,UAAU,IAAI,eAAe,EAAE;IAI/B;;OAEG;IACH,YAAY,IAAI,IAAI;IAIpB;;OAEG;IACH,OAAO,CAAC,aAAa;IAcrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAmBzB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;CAmC9B;AAGD,eAAO,MAAM,WAAW,aAAoB,CAAC"}
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* Enterprise Agent Supervisor - Rate Limiter
|
|
3
3
|
*
|
|
4
4
|
* Token bucket rate limiting with multiple scopes and configurations.
|
|
5
|
+
* Uses extracted utilities from src/utils/rate-limiting.ts for
|
|
6
|
+
* bucket key building and sliding window logic.
|
|
5
7
|
*/
|
|
8
|
+
import { buildBucketKey, SlidingWindow } from '../utils/rate-limiting.js';
|
|
6
9
|
export class RateLimiter {
|
|
7
10
|
configs = new Map();
|
|
8
11
|
buckets = new Map();
|
|
@@ -44,45 +47,37 @@ export class RateLimiter {
|
|
|
44
47
|
continue;
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
|
-
// Build bucket key
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// Reset window: boundary is exclusive on upper bound
|
|
55
|
-
bucket.count = 0;
|
|
56
|
-
bucket.windowStart = now;
|
|
57
|
-
bucket.burstCount = 0;
|
|
58
|
-
}
|
|
59
|
-
// Check limits
|
|
60
|
-
if (bucket.count >= config.maxRequests) {
|
|
61
|
-
const resetAt = new Date(bucket.windowStart + config.windowMs);
|
|
50
|
+
// Build bucket key using extracted utility
|
|
51
|
+
const identifiers = this.toIdentifiers(params);
|
|
52
|
+
const bucketKey = buildBucketKey(config.scope, identifiers, configId);
|
|
53
|
+
const bucket = this.getOrCreateBucket(bucketKey, config);
|
|
54
|
+
// Check if window can accept using SlidingWindow
|
|
55
|
+
if (!bucket.window.canAccept(now)) {
|
|
56
|
+
const stats = bucket.window.getStats(now);
|
|
62
57
|
return {
|
|
63
58
|
allowed: false,
|
|
64
59
|
limitId: configId,
|
|
65
60
|
state: {
|
|
66
61
|
key: bucketKey,
|
|
67
|
-
count:
|
|
68
|
-
windowStart:
|
|
62
|
+
count: stats.count,
|
|
63
|
+
windowStart: stats.windowStart,
|
|
69
64
|
remaining: 0,
|
|
70
|
-
resetAt:
|
|
65
|
+
resetAt: stats.resetAtISO
|
|
71
66
|
}
|
|
72
67
|
};
|
|
73
68
|
}
|
|
74
69
|
// Check burst limit if configured
|
|
75
|
-
if (config.burstLimit && bucket.
|
|
76
|
-
const
|
|
70
|
+
if (config.burstLimit && !bucket.window.canAcceptBurst(now)) {
|
|
71
|
+
const stats = bucket.window.getStats(now);
|
|
77
72
|
return {
|
|
78
73
|
allowed: false,
|
|
79
74
|
limitId: configId,
|
|
80
75
|
state: {
|
|
81
76
|
key: bucketKey,
|
|
82
|
-
count:
|
|
83
|
-
windowStart:
|
|
77
|
+
count: stats.count,
|
|
78
|
+
windowStart: stats.windowStart,
|
|
84
79
|
remaining: 0,
|
|
85
|
-
resetAt:
|
|
80
|
+
resetAt: stats.resetAtISO
|
|
86
81
|
}
|
|
87
82
|
};
|
|
88
83
|
}
|
|
@@ -102,17 +97,11 @@ export class RateLimiter {
|
|
|
102
97
|
continue;
|
|
103
98
|
}
|
|
104
99
|
}
|
|
105
|
-
const
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
bucket.count = 0;
|
|
111
|
-
bucket.windowStart = now;
|
|
112
|
-
bucket.burstCount = 0;
|
|
113
|
-
}
|
|
114
|
-
bucket.count++;
|
|
115
|
-
bucket.burstCount++;
|
|
100
|
+
const identifiers = this.toIdentifiers(params);
|
|
101
|
+
const bucketKey = buildBucketKey(config.scope, identifiers, configId);
|
|
102
|
+
const bucket = this.getOrCreateBucket(bucketKey, config);
|
|
103
|
+
// Record the request in the sliding window
|
|
104
|
+
bucket.window.record(now);
|
|
116
105
|
}
|
|
117
106
|
}
|
|
118
107
|
/**
|
|
@@ -123,7 +112,8 @@ export class RateLimiter {
|
|
|
123
112
|
if (!config)
|
|
124
113
|
return null;
|
|
125
114
|
const now = Date.now();
|
|
126
|
-
const
|
|
115
|
+
const identifiers = this.toIdentifiers(params);
|
|
116
|
+
const bucketKey = buildBucketKey(config.scope, identifiers, configId);
|
|
127
117
|
const bucket = this.buckets.get(bucketKey);
|
|
128
118
|
if (!bucket) {
|
|
129
119
|
return {
|
|
@@ -134,23 +124,13 @@ export class RateLimiter {
|
|
|
134
124
|
resetAt: new Date(now + config.windowMs).toISOString()
|
|
135
125
|
};
|
|
136
126
|
}
|
|
137
|
-
|
|
138
|
-
// Window expires when: now - windowStart >= windowMs
|
|
139
|
-
if (now - bucket.windowStart >= config.windowMs) {
|
|
140
|
-
return {
|
|
141
|
-
key: bucketKey,
|
|
142
|
-
count: 0,
|
|
143
|
-
windowStart: now,
|
|
144
|
-
remaining: config.maxRequests,
|
|
145
|
-
resetAt: new Date(now + config.windowMs).toISOString()
|
|
146
|
-
};
|
|
147
|
-
}
|
|
127
|
+
const stats = bucket.window.getStats(now);
|
|
148
128
|
return {
|
|
149
129
|
key: bucketKey,
|
|
150
|
-
count:
|
|
151
|
-
windowStart:
|
|
152
|
-
remaining:
|
|
153
|
-
resetAt:
|
|
130
|
+
count: stats.count,
|
|
131
|
+
windowStart: stats.windowStart,
|
|
132
|
+
remaining: stats.remaining,
|
|
133
|
+
resetAt: stats.resetAtISO
|
|
154
134
|
};
|
|
155
135
|
}
|
|
156
136
|
/**
|
|
@@ -166,34 +146,30 @@ export class RateLimiter {
|
|
|
166
146
|
this.buckets.clear();
|
|
167
147
|
}
|
|
168
148
|
/**
|
|
169
|
-
*
|
|
149
|
+
* Convert params to BucketIdentifiers for the utility function
|
|
170
150
|
*/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return `${configId}:session:${params.sessionId || 'unknown'}`;
|
|
179
|
-
case 'user':
|
|
180
|
-
return `${configId}:user:${params.userId || 'unknown'}`;
|
|
181
|
-
case 'action_type':
|
|
182
|
-
return `${configId}:action:${params.actionType || 'unknown'}`;
|
|
183
|
-
default:
|
|
184
|
-
return `${configId}:unknown`;
|
|
185
|
-
}
|
|
151
|
+
toIdentifiers(params) {
|
|
152
|
+
return {
|
|
153
|
+
agentId: params.agentId,
|
|
154
|
+
sessionId: params.sessionId,
|
|
155
|
+
userId: params.userId,
|
|
156
|
+
actionType: params.actionType
|
|
157
|
+
};
|
|
186
158
|
}
|
|
187
159
|
/**
|
|
188
|
-
* Get or create a bucket
|
|
160
|
+
* Get or create a bucket with SlidingWindow
|
|
189
161
|
*/
|
|
190
|
-
getOrCreateBucket(key,
|
|
162
|
+
getOrCreateBucket(key, config) {
|
|
191
163
|
let bucket = this.buckets.get(key);
|
|
192
164
|
if (!bucket) {
|
|
193
165
|
bucket = {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
166
|
+
key,
|
|
167
|
+
window: new SlidingWindow({
|
|
168
|
+
windowMs: config.windowMs,
|
|
169
|
+
maxRequests: config.maxRequests,
|
|
170
|
+
burstLimit: config.burstLimit,
|
|
171
|
+
algorithm: 'fixed' // Use fixed window for consistent behavior with original implementation
|
|
172
|
+
})
|
|
197
173
|
};
|
|
198
174
|
this.buckets.set(key, bucket);
|
|
199
175
|
}
|
|
@@ -221,9 +197,10 @@ export class RateLimiter {
|
|
|
221
197
|
// A bucket is expired when: now - windowStart >= 2*maxWindowMs (2x safety margin)
|
|
222
198
|
let removedCount = 0;
|
|
223
199
|
for (const [key, bucket] of this.buckets.entries()) {
|
|
200
|
+
const state = bucket.window.getState();
|
|
224
201
|
// Off-by-one fix: use consistent >= comparison for boundary calculation
|
|
225
202
|
// Window boundary semantics: now - windowStart >= threshold means expired
|
|
226
|
-
if (now -
|
|
203
|
+
if (now - state.windowStart >= maxWindowMs * 2) {
|
|
227
204
|
this.buckets.delete(key);
|
|
228
205
|
removedCount++;
|
|
229
206
|
}
|