ropilot 0.1.42 → 0.1.44
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/lib/proxy.js +119 -36
- package/package.json +1 -1
package/lib/proxy.js
CHANGED
|
@@ -122,13 +122,49 @@ async function handleToolsList(apiKey, request) {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
/**
|
|
125
|
-
*
|
|
125
|
+
* Track script path -> local file mappings for sourcecontrol
|
|
126
|
+
*/
|
|
127
|
+
const scriptLocalFiles = new Map();
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Convert Studio path to local file path in src/ folder
|
|
131
|
+
* e.g., "game.ServerScriptService.MyScript" -> "src/ServerScriptService/MyScript.lua"
|
|
132
|
+
*/
|
|
133
|
+
function studioPathToLocalPath(studioPath) {
|
|
134
|
+
const parts = studioPath.split('.');
|
|
135
|
+
// Remove "game" prefix
|
|
136
|
+
if (parts[0] === 'game') {
|
|
137
|
+
parts.shift();
|
|
138
|
+
}
|
|
139
|
+
// Join with / and add .lua extension
|
|
140
|
+
return join('src', ...parts) + '.lua';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Write script content to local file and track the mapping
|
|
145
|
+
*/
|
|
146
|
+
function writeScriptToLocalFile(scriptPath, content) {
|
|
147
|
+
const localPath = studioPathToLocalPath(scriptPath);
|
|
148
|
+
const dir = join(process.cwd(), localPath.split('/').slice(0, -1).join('/'));
|
|
149
|
+
|
|
150
|
+
mkdirSync(dir, { recursive: true });
|
|
151
|
+
|
|
152
|
+
const fullPath = join(process.cwd(), localPath);
|
|
153
|
+
writeFileSync(fullPath, content);
|
|
154
|
+
|
|
155
|
+
// Track mapping for commitscript
|
|
156
|
+
scriptLocalFiles.set(scriptPath, fullPath);
|
|
157
|
+
|
|
158
|
+
return fullPath;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Write large script content to a temp file (for onboard_action readScript)
|
|
126
163
|
*/
|
|
127
164
|
function writeScriptToTempFile(scriptPath, content) {
|
|
128
165
|
const tempDir = join(tmpdir(), 'ropilot-scripts');
|
|
129
166
|
mkdirSync(tempDir, { recursive: true });
|
|
130
167
|
|
|
131
|
-
// Create a filename from the script path
|
|
132
168
|
const safeName = scriptPath.replace(/[^a-zA-Z0-9]/g, '_');
|
|
133
169
|
const tempFile = join(tempDir, `${safeName}_${randomUUID().slice(0, 8)}.lua`);
|
|
134
170
|
|
|
@@ -136,6 +172,13 @@ function writeScriptToTempFile(scriptPath, content) {
|
|
|
136
172
|
return tempFile;
|
|
137
173
|
}
|
|
138
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Get local file path for a script path
|
|
177
|
+
*/
|
|
178
|
+
function getLocalFileForScript(scriptPath) {
|
|
179
|
+
return scriptLocalFiles.get(scriptPath);
|
|
180
|
+
}
|
|
181
|
+
|
|
139
182
|
/**
|
|
140
183
|
* Handle MCP tools/call request
|
|
141
184
|
*/
|
|
@@ -151,6 +194,38 @@ async function handleToolsCall(apiKey, request) {
|
|
|
151
194
|
};
|
|
152
195
|
}
|
|
153
196
|
|
|
197
|
+
// Handle sourcecontrol_commitscript - inject file content before forwarding
|
|
198
|
+
if (request.params?.name === 'ropilot_sourcecontrol_commitscript') {
|
|
199
|
+
const scriptPath = request.params?.arguments?.path;
|
|
200
|
+
const localFile = getLocalFileForScript(scriptPath);
|
|
201
|
+
|
|
202
|
+
if (!localFile) {
|
|
203
|
+
return {
|
|
204
|
+
jsonrpc: '2.0',
|
|
205
|
+
id: request.id,
|
|
206
|
+
result: {
|
|
207
|
+
content: [{ type: 'text', text: `Error: No local file found for "${scriptPath}". Did you call ropilot_sourcecontrol_requestscript first?` }],
|
|
208
|
+
isError: true
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!existsSync(localFile)) {
|
|
214
|
+
return {
|
|
215
|
+
jsonrpc: '2.0',
|
|
216
|
+
id: request.id,
|
|
217
|
+
result: {
|
|
218
|
+
content: [{ type: 'text', text: `Error: Local file not found: ${localFile}` }],
|
|
219
|
+
isError: true
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Read the file and inject content into the request
|
|
225
|
+
const content = readFileSync(localFile, 'utf-8');
|
|
226
|
+
request.params.arguments.content = content;
|
|
227
|
+
}
|
|
228
|
+
|
|
154
229
|
// Forward to edge
|
|
155
230
|
const response = await forwardToEdge(apiKey, request);
|
|
156
231
|
|
|
@@ -173,6 +248,48 @@ async function handleToolsCall(apiKey, request) {
|
|
|
173
248
|
}
|
|
174
249
|
}
|
|
175
250
|
|
|
251
|
+
// Handle sourcecontrol_requestscript - write to src/ folder
|
|
252
|
+
if (request.params?.name === 'ropilot_sourcecontrol_requestscript') {
|
|
253
|
+
const content = response?.result?.content;
|
|
254
|
+
if (content && Array.isArray(content) && content[0]?.text) {
|
|
255
|
+
const scriptContent = content[0].text;
|
|
256
|
+
const scriptPath = request.params.arguments.path || 'unknown';
|
|
257
|
+
|
|
258
|
+
// Check for error responses
|
|
259
|
+
if (scriptContent.startsWith('Error:')) {
|
|
260
|
+
return response;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Write to src/ folder
|
|
264
|
+
const localFile = writeScriptToLocalFile(scriptPath, scriptContent);
|
|
265
|
+
response.result.content = [{
|
|
266
|
+
type: 'text',
|
|
267
|
+
text: `Script saved to:\n${localFile}\n\nEdit this file, then call ropilot_sourcecontrol_commitscript with path: "${scriptPath}"`
|
|
268
|
+
}];
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Handle sourcecontrol_createscript - auto-write to src/ folder
|
|
273
|
+
if (request.params?.name === 'ropilot_sourcecontrol_createscript') {
|
|
274
|
+
const content = response?.result?.content;
|
|
275
|
+
if (content && Array.isArray(content) && content[0]?.text) {
|
|
276
|
+
const responseText = content[0].text;
|
|
277
|
+
|
|
278
|
+
// Check for CREATED: prefix
|
|
279
|
+
if (responseText.startsWith('CREATED:')) {
|
|
280
|
+
const scriptPath = responseText.replace('CREATED:', '').trim();
|
|
281
|
+
const source = request.params.arguments.source || '';
|
|
282
|
+
|
|
283
|
+
// Write to src/ folder
|
|
284
|
+
const localFile = writeScriptToLocalFile(scriptPath, source);
|
|
285
|
+
response.result.content = [{
|
|
286
|
+
type: 'text',
|
|
287
|
+
text: `Created script: ${scriptPath}\nLocal file: ${localFile}\n\nEdit this file, then call ropilot_sourcecontrol_commitscript with path: "${scriptPath}"`
|
|
288
|
+
}];
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
176
293
|
return response;
|
|
177
294
|
}
|
|
178
295
|
|
|
@@ -269,37 +386,6 @@ async function checkPluginUpdate() {
|
|
|
269
386
|
}
|
|
270
387
|
}
|
|
271
388
|
|
|
272
|
-
/**
|
|
273
|
-
* Try to start rojo serve in background (non-blocking, silent on failure)
|
|
274
|
-
*/
|
|
275
|
-
function tryStartRojoServe() {
|
|
276
|
-
try {
|
|
277
|
-
// Check if default.project.json exists (indicates a Rojo project)
|
|
278
|
-
if (!existsSync(join(process.cwd(), 'default.project.json'))) {
|
|
279
|
-
return; // Not a Rojo project
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// Check if rojo serve is already running
|
|
283
|
-
const check = spawn('pgrep', ['-f', 'rojo serve'], { stdio: 'pipe' });
|
|
284
|
-
check.on('close', (code) => {
|
|
285
|
-
// code 0 = found running process, code 1 = not found
|
|
286
|
-
if (code === 0) {
|
|
287
|
-
return; // Rojo already running
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// Start rojo serve in background
|
|
291
|
-
const child = spawn('rojo', ['serve'], {
|
|
292
|
-
cwd: process.cwd(),
|
|
293
|
-
detached: true,
|
|
294
|
-
stdio: 'ignore',
|
|
295
|
-
shell: true
|
|
296
|
-
});
|
|
297
|
-
child.unref();
|
|
298
|
-
});
|
|
299
|
-
} catch {
|
|
300
|
-
// Silently ignore
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
389
|
|
|
304
390
|
/**
|
|
305
391
|
* Run the stdio MCP server
|
|
@@ -319,9 +405,6 @@ export async function serve() {
|
|
|
319
405
|
// Check for plugin updates in background (non-blocking)
|
|
320
406
|
checkPluginUpdate();
|
|
321
407
|
|
|
322
|
-
// Start rojo serve in background if available (non-blocking, silent on failure)
|
|
323
|
-
tryStartRojoServe();
|
|
324
|
-
|
|
325
408
|
// Read JSON-RPC messages from stdin
|
|
326
409
|
// Supports both Content-Length framing (LSP-style) and newline-delimited JSON
|
|
327
410
|
let buffer = '';
|