@beremaran/godot-agent-loop 1.0.0 → 1.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/README.md +178 -668
- package/addons/godot_agent_loop/README.md +26 -16
- package/addons/godot_agent_loop/plugin.cfg +3 -2
- package/addons/godot_agent_loop/plugin.gd +840 -25
- package/agent-plugin/.claude-plugin/plugin.json +2 -2
- package/agent-plugin/.codex-plugin/plugin.json +3 -3
- package/agent-plugin/.mcp.json +1 -1
- package/agent-plugin/adapter-manifest.json +4 -4
- package/agent-plugin/pi/extension.ts +1 -1
- package/agent-plugin/skills/build-godot-game/SKILL.md +26 -5
- package/agent-plugin/skills/debug-godot-game/SKILL.md +20 -7
- package/agent-plugin/skills/ship-godot-game/SKILL.md +13 -3
- package/agent-plugin/skills/verify-godot-change/SKILL.md +17 -2
- package/build/authoring-session-manager.js +24 -1
- package/build/domain-tool-registries.js +5 -1
- package/build/editor-authoring-router.js +228 -0
- package/build/editor-bridge-protocol.js +2 -1
- package/build/editor-connection.js +29 -24
- package/build/editor-mutation-guard.js +3 -1
- package/build/editor-plugin-installer.js +2 -1
- package/build/editor-session-registry.js +392 -0
- package/build/editor-sync-queue.js +135 -0
- package/build/index.js +208 -29
- package/build/interaction-server-installer.js +1 -1
- package/build/lifecycle-trace.js +80 -0
- package/build/scripts/mcp_editor_plugin.gd +840 -25
- package/build/scripts/mcp_interaction_server.gd +76 -2
- package/build/scripts/mcp_runtime/core_domain.gd +2 -1
- package/build/scripts/mcp_runtime/system_domain.gd +2 -0
- package/build/server-instructions.js +5 -5
- package/build/session-timing.js +17 -1
- package/build/tool-definitions.js +99 -6
- package/build/tool-handlers/game-tool-handlers.js +21 -4
- package/build/tool-handlers/lifecycle-tool-handlers.js +361 -27
- package/build/tool-handlers/project-handler-services.js +50 -8
- package/build/tool-handlers/project-tool-handlers.js +10 -7
- package/build/tool-manifest.js +29 -1
- package/build/tool-mutation-policy.js +1 -0
- package/build/tool-surface.js +4 -4
- package/build/utils.js +14 -3
- package/package.json +5 -5
- package/product.json +9 -7
package/build/tool-manifest.js
CHANGED
|
@@ -18,6 +18,13 @@ export const toolManifest = {
|
|
|
18
18
|
actions: null,
|
|
19
19
|
privileged: false,
|
|
20
20
|
},
|
|
21
|
+
editor_session: {
|
|
22
|
+
domain: 'lifecycle',
|
|
23
|
+
handler: 'handleEditorSession',
|
|
24
|
+
backend: { kind: 'process' },
|
|
25
|
+
actions: ['ensure', 'status', 'disconnect'],
|
|
26
|
+
privileged: false,
|
|
27
|
+
},
|
|
21
28
|
editor_control: {
|
|
22
29
|
domain: 'lifecycle',
|
|
23
30
|
handler: 'handleEditorControl',
|
|
@@ -25,6 +32,13 @@ export const toolManifest = {
|
|
|
25
32
|
actions: ['inspect', 'select', 'save', 'reload', 'open_scene', 'set_property', 'rename_node', 'undo', 'redo'],
|
|
26
33
|
privileged: false,
|
|
27
34
|
},
|
|
35
|
+
editor_transaction: {
|
|
36
|
+
domain: 'lifecycle',
|
|
37
|
+
handler: 'handleEditorTransaction',
|
|
38
|
+
backend: { kind: 'process' },
|
|
39
|
+
actions: null,
|
|
40
|
+
privileged: false,
|
|
41
|
+
},
|
|
28
42
|
run_project: {
|
|
29
43
|
domain: 'lifecycle',
|
|
30
44
|
handler: 'handleRunProject',
|
|
@@ -39,6 +53,20 @@ export const toolManifest = {
|
|
|
39
53
|
actions: null,
|
|
40
54
|
privileged: false,
|
|
41
55
|
},
|
|
56
|
+
game_wait_until: {
|
|
57
|
+
domain: 'lifecycle',
|
|
58
|
+
handler: 'handleGameWaitUntil',
|
|
59
|
+
backend: { kind: 'process' },
|
|
60
|
+
actions: null,
|
|
61
|
+
privileged: false,
|
|
62
|
+
},
|
|
63
|
+
game_scenario: {
|
|
64
|
+
domain: 'lifecycle',
|
|
65
|
+
handler: 'handleGameScenario',
|
|
66
|
+
backend: { kind: 'process' },
|
|
67
|
+
actions: null,
|
|
68
|
+
privileged: false,
|
|
69
|
+
},
|
|
42
70
|
run_project_tests: {
|
|
43
71
|
domain: 'project',
|
|
44
72
|
handler: 'handleRunProjectTests',
|
|
@@ -282,7 +310,7 @@ export const toolManifest = {
|
|
|
282
310
|
domain: 'game',
|
|
283
311
|
handler: 'handleGamePerformance',
|
|
284
312
|
backend: { kind: 'runtime', command: 'get_performance' },
|
|
285
|
-
actions: ['sample', 'start', 'stop', 'report', 'leaks'],
|
|
313
|
+
actions: ['sample', 'start', 'stop', 'report', 'leaks', 'stress'],
|
|
286
314
|
privileged: false,
|
|
287
315
|
},
|
|
288
316
|
game_wait: {
|
package/build/tool-surface.js
CHANGED
|
@@ -7,14 +7,14 @@ export const TOOL_SURFACE_ENV = 'GODOT_MCP_TOOL_SURFACE';
|
|
|
7
7
|
*/
|
|
8
8
|
export const CORE_TOOL_NAMES = new Set([
|
|
9
9
|
'godot_tools',
|
|
10
|
-
'launch_editor', 'editor_control', 'run_project', 'verify_project', 'run_project_tests',
|
|
11
|
-
'get_debug_output', 'stop_project', 'get_godot_version', '
|
|
10
|
+
'launch_editor', 'editor_session', 'editor_control', 'editor_transaction', 'run_project', 'verify_project', 'game_wait_until', 'game_scenario', 'run_project_tests',
|
|
11
|
+
'get_debug_output', 'stop_project', 'get_godot_version', 'get_project_info',
|
|
12
12
|
'create_project', 'create_scene', 'add_node', 'read_scene', 'modify_scene_node',
|
|
13
13
|
'remove_scene_node', 'save_scene', 'create_script', 'attach_script', 'read_file',
|
|
14
14
|
'write_file', 'validate_script', 'validate_scripts', 'read_project_settings',
|
|
15
|
-
'modify_project_settings', '
|
|
15
|
+
'modify_project_settings', 'manage_input_map', 'set_main_scene',
|
|
16
16
|
'game_get_scene_tree', 'game_get_ui', 'game_screenshot', 'game_get_node_info',
|
|
17
|
-
'game_get_errors', 'game_get_logs', '
|
|
17
|
+
'game_get_errors', 'game_get_logs', 'game_click', 'game_key_press',
|
|
18
18
|
'game_key_release',
|
|
19
19
|
]);
|
|
20
20
|
export const TOOL_SURFACE_BUDGETS = {
|
package/build/utils.js
CHANGED
|
@@ -68,9 +68,11 @@ export function validatePath(path) {
|
|
|
68
68
|
}
|
|
69
69
|
/** Centralized filesystem policy for project and project-relative paths. */
|
|
70
70
|
export class PathSecurity {
|
|
71
|
+
realpathResolver;
|
|
71
72
|
allowedRoots;
|
|
72
73
|
supportsRealpath = Object.keys(fs).includes('realpathSync');
|
|
73
|
-
constructor(allowedRoots) {
|
|
74
|
+
constructor(allowedRoots, realpathResolver) {
|
|
75
|
+
this.realpathResolver = realpathResolver;
|
|
74
76
|
const configured = allowedRoots ?? (process.env.GODOT_MCP_ALLOWED_DIRS || '')
|
|
75
77
|
.split(process.platform === 'win32' ? /[;,]/ : /[:,]/)
|
|
76
78
|
.map(value => value.trim())
|
|
@@ -104,6 +106,13 @@ export class PathSecurity {
|
|
|
104
106
|
? candidate
|
|
105
107
|
: null;
|
|
106
108
|
}
|
|
109
|
+
/** Return the allowed project's real path for relative-path calculations. */
|
|
110
|
+
canonicalProjectPath(projectPath) {
|
|
111
|
+
if (!validatePath(projectPath) || !fs.existsSync(projectPath))
|
|
112
|
+
return null;
|
|
113
|
+
const canonical = this.realpathWithFallback(projectPath);
|
|
114
|
+
return this.isWithinAllowedRoots(canonical) ? canonical : null;
|
|
115
|
+
}
|
|
107
116
|
isRelativePathAllowed(projectPath, relativePath) {
|
|
108
117
|
return this.resolveProjectPath(projectPath, relativePath) !== null;
|
|
109
118
|
}
|
|
@@ -117,6 +126,8 @@ export class PathSecurity {
|
|
|
117
126
|
realpathWithFallback(target) {
|
|
118
127
|
const absolute = resolve(target);
|
|
119
128
|
if (fs.existsSync(absolute)) {
|
|
129
|
+
if (this.realpathResolver)
|
|
130
|
+
return this.realpathResolver(absolute);
|
|
120
131
|
const mockedRealpath = (Object.keys(fs).includes('realpathSync'))
|
|
121
132
|
? fs.realpathSync
|
|
122
133
|
: undefined;
|
|
@@ -200,7 +211,7 @@ export function collectGdPaths(outputs) {
|
|
|
200
211
|
}
|
|
201
212
|
return result;
|
|
202
213
|
}
|
|
203
|
-
export const DEFAULT_GODOT_NET_SDK_VERSION = '4.
|
|
214
|
+
export const DEFAULT_GODOT_NET_SDK_VERSION = '4.7.0';
|
|
204
215
|
export const DEFAULT_DOTNET_TARGET_FRAMEWORK = 'net8.0';
|
|
205
216
|
export function toDotnetIdentifier(name) {
|
|
206
217
|
const cleaned = (name || '').replace(/[^A-Za-z0-9_]/g, '_');
|
|
@@ -217,7 +228,7 @@ export function toDotnetNamespace(name) {
|
|
|
217
228
|
export function isValidCsharpIdentifier(name) {
|
|
218
229
|
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);
|
|
219
230
|
}
|
|
220
|
-
export function generateGodotProjectFeatures(isDotnet, version = '4.
|
|
231
|
+
export function generateGodotProjectFeatures(isDotnet, version = '4.7') {
|
|
221
232
|
return isDotnet
|
|
222
233
|
? `PackedStringArray("${version}", "C#")`
|
|
223
234
|
: `PackedStringArray("${version}")`;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@beremaran/godot-agent-loop",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "MCP automation loop with 171 tested tools for Godot 4",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"godot",
|
|
7
7
|
"mcp",
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"gdscript",
|
|
13
13
|
"runtime",
|
|
14
14
|
"agent-workflows",
|
|
15
|
-
"evidence-first",
|
|
16
15
|
"model-context-protocol",
|
|
17
16
|
"pi-package"
|
|
18
17
|
],
|
|
@@ -58,8 +57,9 @@
|
|
|
58
57
|
"watch": "tsc --watch",
|
|
59
58
|
"test": "vitest run",
|
|
60
59
|
"test:watch": "vitest",
|
|
61
|
-
"test:godot": "npm run test:godot:typecheck && npm run test:godot:validate-script && npm run test:godot:operations && npm run test:godot:runtime && npm run test:godot:launch-demo",
|
|
60
|
+
"test:godot": "npm run test:godot:typecheck && npm run test:godot:editor-bridge && npm run test:godot:validate-script && npm run test:godot:operations && npm run test:godot:runtime && npm run test:godot:launch-demo",
|
|
62
61
|
"test:godot:typecheck": "tests/godot/run-typecheck.sh",
|
|
62
|
+
"test:godot:editor-bridge": "tests/godot/run-editor-bridge-tests.sh",
|
|
63
63
|
"test:godot:validate-script": "tests/godot/run-validate-script.sh",
|
|
64
64
|
"test:godot:operations": "tests/godot/run-headless-operations.sh",
|
|
65
65
|
"test:godot:runtime": "tests/godot/run-integration-tests.sh",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"yazl": "^3.3.1"
|
|
98
98
|
},
|
|
99
99
|
"engines": {
|
|
100
|
-
"node": ">=
|
|
100
|
+
"node": ">=22.0.0"
|
|
101
101
|
},
|
|
102
102
|
"pi": {
|
|
103
103
|
"extensions": [
|
package/product.json
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"schemaVersion": 1,
|
|
4
4
|
"name": "Godot Agent Loop",
|
|
5
5
|
"tagline": "Build it. Play it. Prove it.",
|
|
6
|
-
"category": "An
|
|
7
|
-
"description": "
|
|
8
|
-
"version": "1.
|
|
6
|
+
"category": "An MCP automation loop for Godot 4",
|
|
7
|
+
"description": "MCP automation loop with 171 tested tools for Godot 4",
|
|
8
|
+
"version": "1.1.0",
|
|
9
9
|
"repository": {
|
|
10
10
|
"owner": "beremaran",
|
|
11
11
|
"name": "godot-agent-loop",
|
|
@@ -30,11 +30,12 @@
|
|
|
30
30
|
"directory": "addons/godot_agent_loop",
|
|
31
31
|
"name": "Godot Agent Loop Bridge",
|
|
32
32
|
"category": "Addons/Tools",
|
|
33
|
-
"minimumGodotVersion": "4.
|
|
33
|
+
"minimumGodotVersion": "4.7",
|
|
34
34
|
"primaryGodotVersion": "4.7",
|
|
35
|
-
"
|
|
35
|
+
"version": "1.1.0",
|
|
36
|
+
"protocolVersion": "2",
|
|
36
37
|
"license": "MIT",
|
|
37
|
-
"description": "
|
|
38
|
+
"description": "Godot Agent Loop Bridge is an authenticated editor companion that shows live agent activity and compatibility status, provides setup help, and gives you a human Pause/Resume control.",
|
|
38
39
|
"icon": "assets/previews/assetlib-icon.png",
|
|
39
40
|
"previews": [
|
|
40
41
|
"assets/previews/assetlib-editor-overview.png",
|
|
@@ -43,7 +44,8 @@
|
|
|
43
44
|
},
|
|
44
45
|
"observability": {
|
|
45
46
|
"serverComponent": "godot-agent-loop-server",
|
|
46
|
-
"runtimeComponent": "godot-agent-loop-runtime"
|
|
47
|
+
"runtimeComponent": "godot-agent-loop-runtime",
|
|
48
|
+
"editorComponent": "godot-agent-loop-editor"
|
|
47
49
|
},
|
|
48
50
|
"lineage": {
|
|
49
51
|
"originalRepository": "https://github.com/Coding-Solo/godot-mcp",
|