@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.
Files changed (42) hide show
  1. package/README.md +178 -668
  2. package/addons/godot_agent_loop/README.md +26 -16
  3. package/addons/godot_agent_loop/plugin.cfg +3 -2
  4. package/addons/godot_agent_loop/plugin.gd +840 -25
  5. package/agent-plugin/.claude-plugin/plugin.json +2 -2
  6. package/agent-plugin/.codex-plugin/plugin.json +3 -3
  7. package/agent-plugin/.mcp.json +1 -1
  8. package/agent-plugin/adapter-manifest.json +4 -4
  9. package/agent-plugin/pi/extension.ts +1 -1
  10. package/agent-plugin/skills/build-godot-game/SKILL.md +26 -5
  11. package/agent-plugin/skills/debug-godot-game/SKILL.md +20 -7
  12. package/agent-plugin/skills/ship-godot-game/SKILL.md +13 -3
  13. package/agent-plugin/skills/verify-godot-change/SKILL.md +17 -2
  14. package/build/authoring-session-manager.js +24 -1
  15. package/build/domain-tool-registries.js +5 -1
  16. package/build/editor-authoring-router.js +228 -0
  17. package/build/editor-bridge-protocol.js +2 -1
  18. package/build/editor-connection.js +29 -24
  19. package/build/editor-mutation-guard.js +3 -1
  20. package/build/editor-plugin-installer.js +2 -1
  21. package/build/editor-session-registry.js +392 -0
  22. package/build/editor-sync-queue.js +135 -0
  23. package/build/index.js +208 -29
  24. package/build/interaction-server-installer.js +1 -1
  25. package/build/lifecycle-trace.js +80 -0
  26. package/build/scripts/mcp_editor_plugin.gd +840 -25
  27. package/build/scripts/mcp_interaction_server.gd +76 -2
  28. package/build/scripts/mcp_runtime/core_domain.gd +2 -1
  29. package/build/scripts/mcp_runtime/system_domain.gd +2 -0
  30. package/build/server-instructions.js +5 -5
  31. package/build/session-timing.js +17 -1
  32. package/build/tool-definitions.js +99 -6
  33. package/build/tool-handlers/game-tool-handlers.js +21 -4
  34. package/build/tool-handlers/lifecycle-tool-handlers.js +361 -27
  35. package/build/tool-handlers/project-handler-services.js +50 -8
  36. package/build/tool-handlers/project-tool-handlers.js +10 -7
  37. package/build/tool-manifest.js +29 -1
  38. package/build/tool-mutation-policy.js +1 -0
  39. package/build/tool-surface.js +4 -4
  40. package/build/utils.js +14 -3
  41. package/package.json +5 -5
  42. package/product.json +9 -7
@@ -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: {
@@ -7,6 +7,7 @@ import { toolManifest } from './tool-manifest.js';
7
7
  export const READ_ONLY_TOOLS = new Set([
8
8
  'get_debug_output',
9
9
  'get_godot_version',
10
+ 'editor_session',
10
11
  'list_projects',
11
12
  'get_project_info',
12
13
  'get_uid',
@@ -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', 'list_projects', 'get_project_info',
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', 'list_project_files', 'manage_input_map', 'set_main_scene',
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', 'game_wait', 'game_click', 'game_key_press',
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.4.0';
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.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.0.0",
4
- "description": "Evidence-first MCP automation loop with 167 tested tools for Godot 4",
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": ">=18.0.0"
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 evidence-first MCP automation loop for Godot 4",
7
- "description": "Evidence-first MCP automation loop with 167 tested tools for Godot 4",
8
- "version": "1.0.0",
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.4",
33
+ "minimumGodotVersion": "4.7",
34
34
  "primaryGodotVersion": "4.7",
35
- "protocolVersion": "1",
35
+ "version": "1.1.0",
36
+ "protocolVersion": "2",
36
37
  "license": "MIT",
37
- "description": "Authenticated editor companion with live agent activity, compatibility status, setup help, and human Pause/Resume control.",
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",