ghcralph 0.1.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/LICENSE +21 -0
- package/README.md +327 -0
- package/bin/ghcralph.js +2 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +92 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config.d.ts +8 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +118 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/index.d.ts +11 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +11 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +15 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +116 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/rollback.d.ts +8 -0
- package/dist/commands/rollback.d.ts.map +1 -0
- package/dist/commands/rollback.js +238 -0
- package/dist/commands/rollback.js.map +1 -0
- package/dist/commands/run.d.ts +28 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +407 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/status.d.ts +8 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +399 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/core/action-executor.d.ts +96 -0
- package/dist/core/action-executor.d.ts.map +1 -0
- package/dist/core/action-executor.js +289 -0
- package/dist/core/action-executor.js.map +1 -0
- package/dist/core/checkpoint-manager.d.ts +94 -0
- package/dist/core/checkpoint-manager.d.ts.map +1 -0
- package/dist/core/checkpoint-manager.js +236 -0
- package/dist/core/checkpoint-manager.js.map +1 -0
- package/dist/core/config-manager.d.ts +62 -0
- package/dist/core/config-manager.d.ts.map +1 -0
- package/dist/core/config-manager.js +184 -0
- package/dist/core/config-manager.js.map +1 -0
- package/dist/core/config-schema.d.ts +74 -0
- package/dist/core/config-schema.d.ts.map +1 -0
- package/dist/core/config-schema.js +84 -0
- package/dist/core/config-schema.js.map +1 -0
- package/dist/core/context-builder.d.ts +116 -0
- package/dist/core/context-builder.d.ts.map +1 -0
- package/dist/core/context-builder.js +388 -0
- package/dist/core/context-builder.js.map +1 -0
- package/dist/core/feedback-builder.d.ts +94 -0
- package/dist/core/feedback-builder.d.ts.map +1 -0
- package/dist/core/feedback-builder.js +226 -0
- package/dist/core/feedback-builder.js.map +1 -0
- package/dist/core/file-safeguard.d.ts +109 -0
- package/dist/core/file-safeguard.d.ts.map +1 -0
- package/dist/core/file-safeguard.js +200 -0
- package/dist/core/file-safeguard.js.map +1 -0
- package/dist/core/git-branch-manager.d.ts +122 -0
- package/dist/core/git-branch-manager.d.ts.map +1 -0
- package/dist/core/git-branch-manager.js +302 -0
- package/dist/core/git-branch-manager.js.map +1 -0
- package/dist/core/github-plan.d.ts +86 -0
- package/dist/core/github-plan.d.ts.map +1 -0
- package/dist/core/github-plan.js +333 -0
- package/dist/core/github-plan.js.map +1 -0
- package/dist/core/index.d.ts +43 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +26 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/local-markdown-plan.d.ts +65 -0
- package/dist/core/local-markdown-plan.d.ts.map +1 -0
- package/dist/core/local-markdown-plan.js +154 -0
- package/dist/core/local-markdown-plan.js.map +1 -0
- package/dist/core/loop-engine.d.ts +133 -0
- package/dist/core/loop-engine.d.ts.map +1 -0
- package/dist/core/loop-engine.js +420 -0
- package/dist/core/loop-engine.js.map +1 -0
- package/dist/core/loop-events.d.ts +48 -0
- package/dist/core/loop-events.d.ts.map +1 -0
- package/dist/core/loop-events.js +24 -0
- package/dist/core/loop-events.js.map +1 -0
- package/dist/core/loop-state.d.ts +51 -0
- package/dist/core/loop-state.d.ts.map +1 -0
- package/dist/core/loop-state.js +48 -0
- package/dist/core/loop-state.js.map +1 -0
- package/dist/core/markdown-parser.d.ts +51 -0
- package/dist/core/markdown-parser.d.ts.map +1 -0
- package/dist/core/markdown-parser.js +122 -0
- package/dist/core/markdown-parser.js.map +1 -0
- package/dist/core/plan-manager.d.ts +61 -0
- package/dist/core/plan-manager.d.ts.map +1 -0
- package/dist/core/plan-manager.js +7 -0
- package/dist/core/plan-manager.js.map +1 -0
- package/dist/core/progress-tracker.d.ts +74 -0
- package/dist/core/progress-tracker.d.ts.map +1 -0
- package/dist/core/progress-tracker.js +198 -0
- package/dist/core/progress-tracker.js.map +1 -0
- package/dist/core/prompt-examples.d.ts +52 -0
- package/dist/core/prompt-examples.d.ts.map +1 -0
- package/dist/core/prompt-examples.js +194 -0
- package/dist/core/prompt-examples.js.map +1 -0
- package/dist/core/response-parser.d.ts +90 -0
- package/dist/core/response-parser.d.ts.map +1 -0
- package/dist/core/response-parser.js +209 -0
- package/dist/core/response-parser.js.map +1 -0
- package/dist/core/verification-hooks.d.ts +103 -0
- package/dist/core/verification-hooks.d.ts.map +1 -0
- package/dist/core/verification-hooks.js +268 -0
- package/dist/core/verification-hooks.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/auth.d.ts +28 -0
- package/dist/integrations/auth.d.ts.map +1 -0
- package/dist/integrations/auth.js +76 -0
- package/dist/integrations/auth.js.map +1 -0
- package/dist/integrations/copilot-agent.d.ts +104 -0
- package/dist/integrations/copilot-agent.d.ts.map +1 -0
- package/dist/integrations/copilot-agent.js +235 -0
- package/dist/integrations/copilot-agent.js.map +1 -0
- package/dist/integrations/index.d.ts +18 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +14 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/mcp-tools.d.ts +129 -0
- package/dist/integrations/mcp-tools.d.ts.map +1 -0
- package/dist/integrations/mcp-tools.js +272 -0
- package/dist/integrations/mcp-tools.js.map +1 -0
- package/dist/integrations/tokens.d.ts +45 -0
- package/dist/integrations/tokens.d.ts.map +1 -0
- package/dist/integrations/tokens.js +50 -0
- package/dist/integrations/tokens.js.map +1 -0
- package/dist/types/index.d.ts +53 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.d.ts +23 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +37 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/output.d.ts +59 -0
- package/dist/utils/output.d.ts.map +1 -0
- package/dist/utils/output.js +96 -0
- package/dist/utils/output.js.map +1 -0
- package/dist/utils/paths.d.ts +34 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +67 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/shell.d.ts +26 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +65 -0
- package/dist/utils/shell.js.map +1 -0
- package/dist/utils/validation.d.ts +27 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +43 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copilot Agent
|
|
3
|
+
*
|
|
4
|
+
* Integration with GitHub Copilot for AI agent capabilities
|
|
5
|
+
* Uses the @github/copilot-sdk for actual Copilot API access
|
|
6
|
+
*/
|
|
7
|
+
import { CopilotClient } from '@github/copilot-sdk';
|
|
8
|
+
import { debug, error as logError, info, warn } from '../utils/index.js';
|
|
9
|
+
import { getGitHubAuth } from './auth.js';
|
|
10
|
+
import { TokenTracker, estimateTokens } from './tokens.js';
|
|
11
|
+
/**
|
|
12
|
+
* Default agent configuration
|
|
13
|
+
*/
|
|
14
|
+
const DEFAULT_CONFIG = {
|
|
15
|
+
model: 'gpt-4.1',
|
|
16
|
+
maxTokensPerRequest: 4096,
|
|
17
|
+
maxRetries: 3,
|
|
18
|
+
retryDelayMs: 1000,
|
|
19
|
+
cwd: process.cwd(),
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Error types for Copilot API
|
|
23
|
+
*/
|
|
24
|
+
export class CopilotError extends Error {
|
|
25
|
+
code;
|
|
26
|
+
retryable;
|
|
27
|
+
constructor(message, code, retryable = false) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.code = code;
|
|
30
|
+
this.retryable = retryable;
|
|
31
|
+
this.name = 'CopilotError';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Sleep utility for retries
|
|
36
|
+
*/
|
|
37
|
+
function sleep(ms) {
|
|
38
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* CopilotAgent class for interacting with GitHub Copilot
|
|
42
|
+
*/
|
|
43
|
+
export class CopilotAgent {
|
|
44
|
+
config;
|
|
45
|
+
tokenTracker;
|
|
46
|
+
authResult = null;
|
|
47
|
+
initialized = false;
|
|
48
|
+
client = null;
|
|
49
|
+
session = null;
|
|
50
|
+
constructor(config = {}) {
|
|
51
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
52
|
+
this.tokenTracker = new TokenTracker();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Initialize the agent session
|
|
56
|
+
*/
|
|
57
|
+
async initialize() {
|
|
58
|
+
debug('Initializing Copilot agent...');
|
|
59
|
+
// Get authentication
|
|
60
|
+
this.authResult = getGitHubAuth();
|
|
61
|
+
if (!this.authResult.authenticated) {
|
|
62
|
+
logError(this.authResult.error ?? 'Authentication failed');
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
// Create Copilot client
|
|
67
|
+
this.client = new CopilotClient({
|
|
68
|
+
autoStart: true,
|
|
69
|
+
logLevel: 'error',
|
|
70
|
+
});
|
|
71
|
+
// Start the client
|
|
72
|
+
await this.client.start();
|
|
73
|
+
debug('Copilot client started');
|
|
74
|
+
// Create a session with the specified model
|
|
75
|
+
this.session = await this.client.createSession({
|
|
76
|
+
model: this.config.model,
|
|
77
|
+
});
|
|
78
|
+
debug(`Session created with model: ${this.config.model}`);
|
|
79
|
+
info(`Copilot agent initialized (model: ${this.config.model})`);
|
|
80
|
+
this.initialized = true;
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
85
|
+
logError(`Failed to initialize Copilot SDK: ${errorMsg}`);
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if the agent is initialized
|
|
91
|
+
*/
|
|
92
|
+
isInitialized() {
|
|
93
|
+
return this.initialized;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Execute a prompt and get a response
|
|
97
|
+
*/
|
|
98
|
+
async execute(prompt) {
|
|
99
|
+
if (!this.initialized || !this.session) {
|
|
100
|
+
throw new CopilotError('Agent not initialized', 'NOT_INITIALIZED');
|
|
101
|
+
}
|
|
102
|
+
debug(`Executing prompt (${estimateTokens(prompt)} estimated tokens)`);
|
|
103
|
+
let lastError = null;
|
|
104
|
+
for (let attempt = 0; attempt < this.config.maxRetries; attempt++) {
|
|
105
|
+
try {
|
|
106
|
+
const result = await this.executeWithRetry(prompt);
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
111
|
+
if (err instanceof CopilotError && !err.retryable) {
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
if (attempt < this.config.maxRetries - 1) {
|
|
115
|
+
const delay = this.config.retryDelayMs * Math.pow(2, attempt);
|
|
116
|
+
debug(`Retry ${attempt + 1}/${this.config.maxRetries} after ${delay}ms`);
|
|
117
|
+
await sleep(delay);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
success: false,
|
|
123
|
+
error: lastError?.message ?? 'Unknown error',
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Execute with retry logic using Copilot SDK
|
|
128
|
+
*/
|
|
129
|
+
async executeWithRetry(prompt) {
|
|
130
|
+
if (!this.session) {
|
|
131
|
+
throw new CopilotError('No active session', 'NO_SESSION');
|
|
132
|
+
}
|
|
133
|
+
const promptTokens = estimateTokens(prompt);
|
|
134
|
+
let responseContent = '';
|
|
135
|
+
try {
|
|
136
|
+
// Create a promise that resolves when the session becomes idle
|
|
137
|
+
const done = new Promise((resolve, reject) => {
|
|
138
|
+
const timeout = setTimeout(() => {
|
|
139
|
+
reject(new CopilotError('Session timeout', 'TIMEOUT', true));
|
|
140
|
+
}, 120000); // 2 minute timeout
|
|
141
|
+
this.session?.on((event) => {
|
|
142
|
+
if (event.type === 'assistant.message') {
|
|
143
|
+
responseContent += event.data.content ?? '';
|
|
144
|
+
}
|
|
145
|
+
else if (event.type === 'session.idle') {
|
|
146
|
+
clearTimeout(timeout);
|
|
147
|
+
resolve();
|
|
148
|
+
}
|
|
149
|
+
else if (event.type === 'session.error') {
|
|
150
|
+
clearTimeout(timeout);
|
|
151
|
+
reject(new CopilotError(event.data.message ?? 'Unknown error', 'SDK_ERROR', true));
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
// Send the prompt
|
|
156
|
+
await this.session.send({ prompt });
|
|
157
|
+
// Wait for completion
|
|
158
|
+
await done;
|
|
159
|
+
const completionTokens = estimateTokens(responseContent);
|
|
160
|
+
this.tokenTracker.addUsage(promptTokens, completionTokens);
|
|
161
|
+
return {
|
|
162
|
+
success: true,
|
|
163
|
+
content: responseContent,
|
|
164
|
+
tokenUsage: {
|
|
165
|
+
promptTokens,
|
|
166
|
+
completionTokens,
|
|
167
|
+
totalTokens: promptTokens + completionTokens,
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
173
|
+
warn(`Copilot execution error: ${errorMsg}`);
|
|
174
|
+
throw err;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Cleanup resources
|
|
179
|
+
*/
|
|
180
|
+
async destroy() {
|
|
181
|
+
try {
|
|
182
|
+
if (this.session) {
|
|
183
|
+
await this.session.destroy();
|
|
184
|
+
this.session = null;
|
|
185
|
+
}
|
|
186
|
+
if (this.client) {
|
|
187
|
+
await this.client.stop();
|
|
188
|
+
this.client = null;
|
|
189
|
+
}
|
|
190
|
+
this.initialized = false;
|
|
191
|
+
debug('Copilot agent destroyed');
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
warn(`Error during cleanup: ${err instanceof Error ? err.message : String(err)}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Get total token usage
|
|
199
|
+
*/
|
|
200
|
+
getTokenUsage() {
|
|
201
|
+
return this.tokenTracker.getUsage();
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Reset token tracking
|
|
205
|
+
*/
|
|
206
|
+
resetTokenUsage() {
|
|
207
|
+
this.tokenTracker.reset();
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Check if token budget is exceeded
|
|
211
|
+
*/
|
|
212
|
+
isTokenBudgetExceeded(maxTokens) {
|
|
213
|
+
return this.tokenTracker.exceedsLimit(maxTokens);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Get the current model
|
|
217
|
+
*/
|
|
218
|
+
getModel() {
|
|
219
|
+
return this.config.model;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Set the model
|
|
223
|
+
*/
|
|
224
|
+
setModel(model) {
|
|
225
|
+
this.config.model = model;
|
|
226
|
+
debug(`Model set to: ${model}`);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Get the current configuration
|
|
230
|
+
*/
|
|
231
|
+
getConfig() {
|
|
232
|
+
return { ...this.config };
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=copilot-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilot-agent.js","sourceRoot":"","sources":["../../src/integrations/copilot-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integrations
|
|
3
|
+
*
|
|
4
|
+
* This module contains integrations with:
|
|
5
|
+
* - GitHub Copilot SDK
|
|
6
|
+
* - GitHub API (for Issues)
|
|
7
|
+
* - Git operations
|
|
8
|
+
* - MCP Tools
|
|
9
|
+
*/
|
|
10
|
+
export { CopilotAgent, CopilotError } from './copilot-agent.js';
|
|
11
|
+
export type { CopilotModel, CopilotAgentConfig, ExecutionResult } from './copilot-agent.js';
|
|
12
|
+
export { getGitHubAuth, isAuthenticated } from './auth.js';
|
|
13
|
+
export type { AuthResult } from './auth.js';
|
|
14
|
+
export { TokenTracker, estimateTokens } from './tokens.js';
|
|
15
|
+
export type { TokenUsage } from './tokens.js';
|
|
16
|
+
export { MCPToolManager, createMCPToolManager } from './mcp-tools.js';
|
|
17
|
+
export type { MCPServerConfig, MCPTool, MCPToolResult, MCPServerConnection } from './mcp-tools.js';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE5F,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC3D,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC3D,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtE,YAAY,EAAE,eAAe,EAAE,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integrations
|
|
3
|
+
*
|
|
4
|
+
* This module contains integrations with:
|
|
5
|
+
* - GitHub Copilot SDK
|
|
6
|
+
* - GitHub API (for Issues)
|
|
7
|
+
* - Git operations
|
|
8
|
+
* - MCP Tools
|
|
9
|
+
*/
|
|
10
|
+
export { CopilotAgent, CopilotError } from './copilot-agent.js';
|
|
11
|
+
export { getGitHubAuth, isAuthenticated } from './auth.js';
|
|
12
|
+
export { TokenTracker, estimateTokens } from './tokens.js';
|
|
13
|
+
export { MCPToolManager, createMCPToolManager } from './mcp-tools.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGhE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool Extension Support
|
|
3
|
+
*
|
|
4
|
+
* Allows users to extend Ralph with custom MCP (Model Context Protocol) tools.
|
|
5
|
+
*/
|
|
6
|
+
import { type ChildProcess } from 'node:child_process';
|
|
7
|
+
/**
|
|
8
|
+
* MCP Server configuration
|
|
9
|
+
*/
|
|
10
|
+
export interface MCPServerConfig {
|
|
11
|
+
/** Name of the MCP server */
|
|
12
|
+
name: string;
|
|
13
|
+
/** Command to run the server */
|
|
14
|
+
command: string;
|
|
15
|
+
/** Arguments to pass to the command */
|
|
16
|
+
args?: string[];
|
|
17
|
+
/** Environment variables */
|
|
18
|
+
env?: Record<string, string>;
|
|
19
|
+
/** Transport type (stdio or http) */
|
|
20
|
+
transport?: 'stdio' | 'http';
|
|
21
|
+
/** HTTP endpoint (for http transport) */
|
|
22
|
+
endpoint?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* MCP Tool definition
|
|
26
|
+
*/
|
|
27
|
+
export interface MCPTool {
|
|
28
|
+
/** Tool name */
|
|
29
|
+
name: string;
|
|
30
|
+
/** Tool description */
|
|
31
|
+
description: string;
|
|
32
|
+
/** Input schema (JSON Schema) */
|
|
33
|
+
inputSchema?: Record<string, unknown>;
|
|
34
|
+
/** Server this tool belongs to */
|
|
35
|
+
server: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* MCP Tool result
|
|
39
|
+
*/
|
|
40
|
+
export interface MCPToolResult {
|
|
41
|
+
/** Whether the tool execution succeeded */
|
|
42
|
+
success: boolean;
|
|
43
|
+
/** Result content */
|
|
44
|
+
content?: string;
|
|
45
|
+
/** Error message if failed */
|
|
46
|
+
error?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* MCP Server connection
|
|
50
|
+
*/
|
|
51
|
+
export interface MCPServerConnection {
|
|
52
|
+
/** Server configuration */
|
|
53
|
+
config: MCPServerConfig;
|
|
54
|
+
/** Available tools */
|
|
55
|
+
tools: MCPTool[];
|
|
56
|
+
/** Whether connected */
|
|
57
|
+
connected: boolean;
|
|
58
|
+
/** Server process (for stdio transport) */
|
|
59
|
+
process?: ChildProcess;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* MCP Tool Manager
|
|
63
|
+
*
|
|
64
|
+
* Manages connections to MCP servers and tool execution
|
|
65
|
+
*/
|
|
66
|
+
export declare class MCPToolManager {
|
|
67
|
+
private servers;
|
|
68
|
+
/**
|
|
69
|
+
* Add an MCP server configuration
|
|
70
|
+
*/
|
|
71
|
+
addServer(config: MCPServerConfig): void;
|
|
72
|
+
/**
|
|
73
|
+
* Add multiple servers from configuration
|
|
74
|
+
*/
|
|
75
|
+
addServers(configs: MCPServerConfig[]): void;
|
|
76
|
+
/**
|
|
77
|
+
* Connect to an MCP server and discover tools
|
|
78
|
+
*/
|
|
79
|
+
connect(serverName: string): Promise<boolean>;
|
|
80
|
+
/**
|
|
81
|
+
* Connect via stdio transport
|
|
82
|
+
*/
|
|
83
|
+
private connectStdio;
|
|
84
|
+
/**
|
|
85
|
+
* Connect via HTTP transport
|
|
86
|
+
*/
|
|
87
|
+
private connectHttp;
|
|
88
|
+
/**
|
|
89
|
+
* Connect to all configured servers
|
|
90
|
+
*/
|
|
91
|
+
connectAll(): Promise<number>;
|
|
92
|
+
/**
|
|
93
|
+
* Get all available tools from connected servers
|
|
94
|
+
*/
|
|
95
|
+
getAvailableTools(): MCPTool[];
|
|
96
|
+
/**
|
|
97
|
+
* Execute a tool
|
|
98
|
+
*/
|
|
99
|
+
executeTool(toolName: string, input: Record<string, unknown>): Promise<MCPToolResult>;
|
|
100
|
+
/**
|
|
101
|
+
* Execute a tool on a specific server
|
|
102
|
+
*/
|
|
103
|
+
private executeOnServer;
|
|
104
|
+
/**
|
|
105
|
+
* Execute via stdio
|
|
106
|
+
*/
|
|
107
|
+
private executeStdio;
|
|
108
|
+
/**
|
|
109
|
+
* Execute via HTTP
|
|
110
|
+
*/
|
|
111
|
+
private executeHttp;
|
|
112
|
+
/**
|
|
113
|
+
* Disconnect from all servers
|
|
114
|
+
*/
|
|
115
|
+
disconnect(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Get server names
|
|
118
|
+
*/
|
|
119
|
+
getServerNames(): string[];
|
|
120
|
+
/**
|
|
121
|
+
* Check if a server is connected
|
|
122
|
+
*/
|
|
123
|
+
isConnected(serverName: string): boolean;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Create an MCP tool manager
|
|
127
|
+
*/
|
|
128
|
+
export declare function createMCPToolManager(): MCPToolManager;
|
|
129
|
+
//# sourceMappingURL=mcp-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-tools.d.ts","sourceRoot":"","sources":["../../src/integrations/mcp-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG9D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,4BAA4B;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,qCAAqC;IACrC,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,2BAA2B;IAC3B,MAAM,EAAE,eAAe,CAAC;IACxB,sBAAsB;IACtB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,wBAAwB;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAED;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAA+C;IAE9D;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAcxC;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI;IAM5C;;OAEG;IACG,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqBnD;;OAEG;YACW,YAAY;IAgD1B;;OAEG;YACW,WAAW;IA4BzB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAUnC;;OAEG;IACH,iBAAiB,IAAI,OAAO,EAAE;IAU9B;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IAe3F;;OAEG;YACW,eAAe;IAqB7B;;OAEG;IACH,OAAO,CAAC,YAAY;IAmCpB;;OAEG;YACW,WAAW;IAoBzB;;OAEG;IACH,UAAU,IAAI,IAAI;IAWlB;;OAEG;IACH,cAAc,IAAI,MAAM,EAAE;IAI1B;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;CAGzC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAErD"}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool Extension Support
|
|
3
|
+
*
|
|
4
|
+
* Allows users to extend Ralph with custom MCP (Model Context Protocol) tools.
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
7
|
+
import { debug, warn, info } from '../utils/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* MCP Tool Manager
|
|
10
|
+
*
|
|
11
|
+
* Manages connections to MCP servers and tool execution
|
|
12
|
+
*/
|
|
13
|
+
export class MCPToolManager {
|
|
14
|
+
servers = new Map();
|
|
15
|
+
/**
|
|
16
|
+
* Add an MCP server configuration
|
|
17
|
+
*/
|
|
18
|
+
addServer(config) {
|
|
19
|
+
if (this.servers.has(config.name)) {
|
|
20
|
+
warn(`MCP server '${config.name}' already exists, replacing`);
|
|
21
|
+
}
|
|
22
|
+
this.servers.set(config.name, {
|
|
23
|
+
config,
|
|
24
|
+
tools: [],
|
|
25
|
+
connected: false,
|
|
26
|
+
});
|
|
27
|
+
debug(`Added MCP server: ${config.name}`);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Add multiple servers from configuration
|
|
31
|
+
*/
|
|
32
|
+
addServers(configs) {
|
|
33
|
+
for (const config of configs) {
|
|
34
|
+
this.addServer(config);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Connect to an MCP server and discover tools
|
|
39
|
+
*/
|
|
40
|
+
async connect(serverName) {
|
|
41
|
+
const connection = this.servers.get(serverName);
|
|
42
|
+
if (!connection) {
|
|
43
|
+
warn(`MCP server '${serverName}' not found`);
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
const { config } = connection;
|
|
47
|
+
try {
|
|
48
|
+
if (config.transport === 'http') {
|
|
49
|
+
return await this.connectHttp(connection);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
return await this.connectStdio(connection);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
warn(`Failed to connect to MCP server '${serverName}': ${err instanceof Error ? err.message : String(err)}`);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Connect via stdio transport
|
|
62
|
+
*/
|
|
63
|
+
async connectStdio(connection) {
|
|
64
|
+
const { config } = connection;
|
|
65
|
+
const childProcess = spawn(config.command, config.args ?? [], {
|
|
66
|
+
env: { ...globalThis.process.env, ...config.env },
|
|
67
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
68
|
+
});
|
|
69
|
+
connection.process = childProcess;
|
|
70
|
+
// Wait for initialization
|
|
71
|
+
return new Promise((resolve) => {
|
|
72
|
+
const timeout = setTimeout(() => {
|
|
73
|
+
debug(`MCP server '${config.name}' connection timeout`);
|
|
74
|
+
resolve(false);
|
|
75
|
+
}, 5000);
|
|
76
|
+
childProcess.stdout?.once('data', (data) => {
|
|
77
|
+
clearTimeout(timeout);
|
|
78
|
+
try {
|
|
79
|
+
// Parse initialization response
|
|
80
|
+
const response = JSON.parse(data.toString());
|
|
81
|
+
if (response.tools) {
|
|
82
|
+
connection.tools = response.tools.map((t) => ({
|
|
83
|
+
...t,
|
|
84
|
+
server: config.name,
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
connection.connected = true;
|
|
88
|
+
info(`Connected to MCP server '${config.name}' with ${connection.tools.length} tools`);
|
|
89
|
+
resolve(true);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
debug(`Failed to parse MCP server response`);
|
|
93
|
+
resolve(false);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
childProcess.on('error', (err) => {
|
|
97
|
+
clearTimeout(timeout);
|
|
98
|
+
debug(`MCP server '${config.name}' error: ${err.message}`);
|
|
99
|
+
resolve(false);
|
|
100
|
+
});
|
|
101
|
+
// Send initialization request
|
|
102
|
+
childProcess.stdin?.write(JSON.stringify({ method: 'initialize' }) + '\n');
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Connect via HTTP transport
|
|
107
|
+
*/
|
|
108
|
+
async connectHttp(connection) {
|
|
109
|
+
const { config } = connection;
|
|
110
|
+
if (!config.endpoint) {
|
|
111
|
+
warn(`MCP server '${config.name}' has no endpoint configured`);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
const response = await fetch(`${config.endpoint}/tools`, {
|
|
116
|
+
method: 'GET',
|
|
117
|
+
headers: { 'Content-Type': 'application/json' },
|
|
118
|
+
});
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
const data = await response.json();
|
|
123
|
+
connection.tools = (data.tools ?? []).map(t => ({ ...t, server: config.name }));
|
|
124
|
+
connection.connected = true;
|
|
125
|
+
info(`Connected to MCP server '${config.name}' with ${connection.tools.length} tools`);
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Connect to all configured servers
|
|
134
|
+
*/
|
|
135
|
+
async connectAll() {
|
|
136
|
+
let connected = 0;
|
|
137
|
+
for (const [name] of this.servers) {
|
|
138
|
+
if (await this.connect(name)) {
|
|
139
|
+
connected++;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return connected;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get all available tools from connected servers
|
|
146
|
+
*/
|
|
147
|
+
getAvailableTools() {
|
|
148
|
+
const tools = [];
|
|
149
|
+
for (const connection of this.servers.values()) {
|
|
150
|
+
if (connection.connected) {
|
|
151
|
+
tools.push(...connection.tools);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return tools;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Execute a tool
|
|
158
|
+
*/
|
|
159
|
+
async executeTool(toolName, input) {
|
|
160
|
+
// Find the tool
|
|
161
|
+
for (const connection of this.servers.values()) {
|
|
162
|
+
const tool = connection.tools.find(t => t.name === toolName);
|
|
163
|
+
if (tool && connection.connected) {
|
|
164
|
+
return this.executeOnServer(connection, toolName, input);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
success: false,
|
|
169
|
+
error: `Tool '${toolName}' not found`,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Execute a tool on a specific server
|
|
174
|
+
*/
|
|
175
|
+
async executeOnServer(connection, toolName, input) {
|
|
176
|
+
const { config } = connection;
|
|
177
|
+
try {
|
|
178
|
+
if (config.transport === 'http') {
|
|
179
|
+
return await this.executeHttp(config, toolName, input);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
return await this.executeStdio(connection, toolName, input);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
return {
|
|
187
|
+
success: false,
|
|
188
|
+
error: err instanceof Error ? err.message : String(err),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Execute via stdio
|
|
194
|
+
*/
|
|
195
|
+
executeStdio(connection, toolName, input) {
|
|
196
|
+
return new Promise((resolve) => {
|
|
197
|
+
if (!connection.process?.stdin || !connection.process?.stdout) {
|
|
198
|
+
resolve({ success: false, error: 'Server process not available' });
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const timeout = setTimeout(() => {
|
|
202
|
+
resolve({ success: false, error: 'Execution timeout' });
|
|
203
|
+
}, 30000);
|
|
204
|
+
connection.process.stdout.once('data', (data) => {
|
|
205
|
+
clearTimeout(timeout);
|
|
206
|
+
try {
|
|
207
|
+
const response = JSON.parse(data.toString());
|
|
208
|
+
resolve({
|
|
209
|
+
success: !response.error,
|
|
210
|
+
content: response.result,
|
|
211
|
+
error: response.error,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
resolve({ success: false, error: 'Failed to parse response' });
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
connection.process.stdin.write(JSON.stringify({ method: 'execute', tool: toolName, input }) + '\n');
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Execute via HTTP
|
|
223
|
+
*/
|
|
224
|
+
async executeHttp(config, toolName, input) {
|
|
225
|
+
const response = await fetch(`${config.endpoint}/execute`, {
|
|
226
|
+
method: 'POST',
|
|
227
|
+
headers: { 'Content-Type': 'application/json' },
|
|
228
|
+
body: JSON.stringify({ tool: toolName, input }),
|
|
229
|
+
});
|
|
230
|
+
const data = await response.json();
|
|
231
|
+
const result = {
|
|
232
|
+
success: response.ok && !data.error,
|
|
233
|
+
};
|
|
234
|
+
if (data.result !== undefined)
|
|
235
|
+
result.content = data.result;
|
|
236
|
+
if (data.error !== undefined)
|
|
237
|
+
result.error = data.error;
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Disconnect from all servers
|
|
242
|
+
*/
|
|
243
|
+
disconnect() {
|
|
244
|
+
for (const connection of this.servers.values()) {
|
|
245
|
+
if (connection.process) {
|
|
246
|
+
connection.process.kill();
|
|
247
|
+
delete connection.process;
|
|
248
|
+
}
|
|
249
|
+
connection.connected = false;
|
|
250
|
+
}
|
|
251
|
+
debug('Disconnected from all MCP servers');
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Get server names
|
|
255
|
+
*/
|
|
256
|
+
getServerNames() {
|
|
257
|
+
return Array.from(this.servers.keys());
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Check if a server is connected
|
|
261
|
+
*/
|
|
262
|
+
isConnected(serverName) {
|
|
263
|
+
return this.servers.get(serverName)?.connected ?? false;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Create an MCP tool manager
|
|
268
|
+
*/
|
|
269
|
+
export function createMCPToolManager() {
|
|
270
|
+
return new MCPToolManager();
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=mcp-tools.js.map
|