mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 05:51:39 +00:00
Implement get_script command for improved script retrieval in MCP
- Introduced a new `get_script` command to allow agents to read script source code directly from Roblox Studio, enhancing conflict resolution during sync operations. - Updated the MCP stream handling to support the new command, including error handling for missing or invalid parameters. - Enhanced the App component to manage the `get_script` command and its response, ensuring proper integration with the existing MCP functionality. - Updated the TODO list to reflect the addition of the `get_script` command and its associated documentation requirements. These changes aim to improve the overall functionality and user experience of the MCP integration, particularly in script management.
This commit is contained in:
parent
9aa3145b06
commit
fd49602adb
8 changed files with 1487 additions and 207 deletions
|
|
@ -211,6 +211,9 @@ function App:init()
|
|||
onSyncCommand = function(requestId, mode, overrides)
|
||||
return self:startMcpSync(requestId, mode, overrides)
|
||||
end,
|
||||
onGetScriptCommand = function(requestId, data)
|
||||
return self:handleMcpGetScript(requestId, data)
|
||||
end,
|
||||
getPluginConfig = function(key)
|
||||
return Settings:get(key)
|
||||
end,
|
||||
|
|
@ -239,6 +242,7 @@ function App:willUnmount()
|
|||
if self.mcpStream then
|
||||
self.mcpStream:stop()
|
||||
self.mcpStream = nil
|
||||
self._lastMcpFromIds = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1186,6 +1190,12 @@ function App:startMcpSync(requestId, mode, overrides)
|
|||
serveSession:setConfirmCallback(function(instanceMap, patch, serverInfo)
|
||||
cachedServerInfo = serverInfo
|
||||
|
||||
local retainedFromIds = {}
|
||||
for id, inst in instanceMap.fromIds do
|
||||
retainedFromIds[id] = inst
|
||||
end
|
||||
self._lastMcpFromIds = retainedFromIds
|
||||
|
||||
PatchSet.removeDataModelName(patch, instanceMap)
|
||||
|
||||
if PatchSet.isEmpty(patch) then
|
||||
|
|
@ -1538,6 +1548,85 @@ function App:_buildMcpChangeList(patchTree, patch, instanceMap, selections, incl
|
|||
return changes
|
||||
end
|
||||
|
||||
function App:handleMcpGetScript(requestId, params)
|
||||
local ScriptEditorService = game:GetService("ScriptEditorService")
|
||||
|
||||
return Promise.resolve():andThen(function()
|
||||
local fromIds = self._lastMcpFromIds
|
||||
if not fromIds then
|
||||
return {
|
||||
requestId = requestId,
|
||||
status = "error",
|
||||
message = 'No previous sync session. Run atlas_sync(mode: "dryrun") first to establish the instance mapping.',
|
||||
}
|
||||
end
|
||||
|
||||
local id = params.id
|
||||
if not id then
|
||||
return {
|
||||
requestId = requestId,
|
||||
status = "error",
|
||||
message = "No id provided. The server should have resolved fsPath to an id.",
|
||||
}
|
||||
end
|
||||
|
||||
local instance = fromIds[id]
|
||||
if not instance then
|
||||
return {
|
||||
requestId = requestId,
|
||||
status = "error",
|
||||
message = "Instance not found by id. The sync session may be stale, run atlas_sync again.",
|
||||
}
|
||||
end
|
||||
if instance.Parent == nil then
|
||||
return {
|
||||
requestId = requestId,
|
||||
status = "error",
|
||||
message = "Instance was deleted since last sync. Run atlas_sync again.",
|
||||
}
|
||||
end
|
||||
|
||||
if not instance:IsA("LuaSourceContainer") then
|
||||
return {
|
||||
requestId = requestId,
|
||||
status = "error",
|
||||
message = `Instance is not a script (class: {instance.ClassName})`,
|
||||
}
|
||||
end
|
||||
|
||||
local source
|
||||
local isDraft = params.fromDraft == true
|
||||
if isDraft then
|
||||
local ok, draft = pcall(ScriptEditorService.GetEditorSource, ScriptEditorService, instance)
|
||||
if ok then
|
||||
source = draft
|
||||
else
|
||||
source = instance.Source
|
||||
isDraft = false
|
||||
end
|
||||
else
|
||||
source = instance.Source
|
||||
end
|
||||
|
||||
local gitBlob = "blob " .. tostring(#source) .. "\0" .. source
|
||||
local studioHash = SHA1(buffer.fromstring(gitBlob))
|
||||
|
||||
local fullName = instance:GetFullName()
|
||||
local instancePath = string.gsub(fullName, "^game%.", "")
|
||||
instancePath = string.gsub(instancePath, "%.", "/")
|
||||
|
||||
return {
|
||||
requestId = requestId,
|
||||
status = "success",
|
||||
source = source,
|
||||
studioHash = studioHash,
|
||||
className = instance.ClassName,
|
||||
instancePath = instancePath,
|
||||
isDraft = isDraft,
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
function App:render()
|
||||
local pluginName = "Atlas " .. Version.display(Config.version)
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ function McpStream.new(options)
|
|||
local self = setmetatable({}, McpStream)
|
||||
|
||||
self._onSyncCommand = options.onSyncCommand
|
||||
self._onGetScriptCommand = options.onGetScriptCommand
|
||||
self._getPluginConfig = options.getPluginConfig
|
||||
self._wsClient = nil
|
||||
self._running = false
|
||||
|
|
@ -125,6 +126,33 @@ function McpStream:_tryConnect()
|
|||
end)
|
||||
end
|
||||
end)
|
||||
elseif data.type == "getScript" and data.requestId then
|
||||
Log.info("MCP stream: received getScript command (requestId={})", data.requestId)
|
||||
|
||||
local resultPromise = self._onGetScriptCommand(data.requestId, data)
|
||||
|
||||
resultPromise
|
||||
:andThen(function(result)
|
||||
if self._wsClient then
|
||||
local json = HttpService:JSONEncode(result)
|
||||
pcall(function()
|
||||
self._wsClient:Send(json)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
:catch(function(err)
|
||||
Log.warn("MCP stream: getScript command failed: {}", tostring(err))
|
||||
if self._wsClient then
|
||||
local errorResult = HttpService:JSONEncode({
|
||||
requestId = data.requestId,
|
||||
status = "error",
|
||||
message = tostring(err),
|
||||
})
|
||||
pcall(function()
|
||||
self._wsClient:Send(errorResult)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue