godot-cli 0.13.3 → 0.15.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.
@@ -0,0 +1,249 @@
1
+ // Pure, behaviorally-identical TS port of the dock's extension-install logic
2
+ // (`addons/godot_mcp/Runtime/Extensions/ExtensionInstallPlanner.cs` +
3
+ // `InstalledStateDetector.CompareVersions`). It computes the add / update / no-op
4
+ // plan AND the resulting `.csproj` text from a descriptor + the current `.csproj`,
5
+ // preserving every other `<PackageReference>` and unrelated XML.
6
+ //
7
+ // Parity contract (verified by `cli/tests/extension-install.test.ts` against the
8
+ // SAME scenario set as `Godot-MCP.Tests/ExtensionInstallTests.cs`):
9
+ // - absent reference → ADD (append; Version="<pin>" when pinned, Version="*" when unpinned/floating)
10
+ // - present, descriptor newer → UPDATE (bump version, honoring attr vs child form)
11
+ // - present, no version, pinned → UPDATE (set the descriptor's pin)
12
+ // - present, no version, unpinned → UPDATE (SELF-HEAL the NU1015-prone versionless reference to Version="*")
13
+ // - present, equal/newer → NO-OP
14
+ // - descriptor unpinned, present with a version → NO-OP (never downgrade a concrete pin to "*")
15
+ // - version compare is numeric + tolerant (1.10.0 > 1.2.0; trailing 0; suffix-tolerant)
16
+ //
17
+ // A versionless `<PackageReference Include="x" />` fails NuGet restore with NU1015, so an
18
+ // unpinned (null-version) descriptor's "float to latest" intent is materialized as
19
+ // `Version="*"` — mirroring the C# planner's `FloatVersion` constant byte-for-byte.
20
+ //
21
+ // The C# planner uses System.Xml.Linq; this uses scoped text edits (like the CLI's
22
+ // existing `csproj-deps.ts`) so the consumer's formatting is preserved verbatim. The
23
+ // add/update/no-op DECISION and the resulting parsed PackageReferences are identical.
24
+ //
25
+ // No top-level side effects; pure string transforms only.
26
+ import { hasVersion } from './extensions-catalog.js';
27
+ /**
28
+ * The MSBuild floating-version marker written for an UNPINNED (null/empty-version) descriptor.
29
+ * A versionless `<PackageReference Include="x" />` fails NuGet restore with NU1015, so the
30
+ * "float to latest" intent is materialized as `Version="*"`. Mirrors C# `ExtensionInstallPlanner.FloatVersion`.
31
+ */
32
+ export const FLOAT_VERSION = '*';
33
+ /** Thrown by {@link planExtensionInstall} on a genuinely unparseable `.csproj` (the lib turns it into a structured failure). */
34
+ export class CsprojParseError extends Error {
35
+ }
36
+ /** Escape a string for use inside a RegExp source. */
37
+ function escapeRegExp(value) {
38
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
39
+ }
40
+ /**
41
+ * Compare two dotted numeric version strings component-by-component as integers
42
+ * (so `1.10.0` > `1.2.0`, unlike an ordinal string compare). A trailing pre-release
43
+ * / build suffix on a component (`1.0.0-rc1`) is tolerated — only the leading integer
44
+ * of each component is read; a non-numeric component reads as 0. Missing trailing
45
+ * components are treated as 0 (`1.0` === `1.0.0`). Returns >0 when `a` is newer, <0
46
+ * when older, 0 when equal. Exact port of C# `InstalledStateDetector.CompareVersions`.
47
+ */
48
+ export function compareVersions(a, b) {
49
+ const pa = splitComponents(a);
50
+ const pb = splitComponents(b);
51
+ const n = Math.max(pa.length, pb.length);
52
+ for (let i = 0; i < n; i++) {
53
+ const ca = i < pa.length ? pa[i] : 0;
54
+ const cb = i < pb.length ? pb[i] : 0;
55
+ if (ca !== cb)
56
+ return ca < cb ? -1 : 1;
57
+ }
58
+ return 0;
59
+ }
60
+ function splitComponents(version) {
61
+ if (version === null || version === undefined || version.trim() === '')
62
+ return [];
63
+ return version
64
+ .trim()
65
+ .split('.')
66
+ .map((part) => leadingInt(part));
67
+ }
68
+ function leadingInt(component) {
69
+ let end = 0;
70
+ while (end < component.length && component[end] >= '0' && component[end] <= '9')
71
+ end++;
72
+ if (end === 0)
73
+ return 0;
74
+ const value = Number.parseInt(component.slice(0, end), 10);
75
+ return Number.isNaN(value) ? 0 : value;
76
+ }
77
+ /**
78
+ * Parse every `<PackageReference>` in the `.csproj` into a `{ packageId → version }`
79
+ * map (ids lower-cased — NuGet ids are case-insensitive; value is the `Version`
80
+ * attribute, else a child `<Version>` element, else `''`). Returns an EMPTY map for
81
+ * empty/whitespace input. Port of C# `InstalledStateDetector.ParsePackageReferences`
82
+ * (the CLI never needs the bad-XML tolerance branch — the planner validates first).
83
+ */
84
+ export function parsePackageReferences(csprojText) {
85
+ const map = new Map();
86
+ if (csprojText === null || csprojText === undefined || csprojText.trim() === '')
87
+ return map;
88
+ const elementRe = /<PackageReference\b[^>]*?(?:\/>|>[\s\S]*?<\/PackageReference>)/gi;
89
+ let m;
90
+ while ((m = elementRe.exec(csprojText)) !== null) {
91
+ const element = m[0];
92
+ const include = /\bInclude\s*=\s*"([^"]*)"/i.exec(element);
93
+ if (!include || include[1].trim() === '')
94
+ continue;
95
+ map.set(include[1].trim().toLowerCase(), readElementVersion(element));
96
+ }
97
+ return map;
98
+ }
99
+ /** Read the version off a single matched `<PackageReference>` element (attribute form, else child element; `''` when unversioned). */
100
+ function readElementVersion(element) {
101
+ const attr = /\bVersion\s*=\s*"([^"]*)"/i.exec(element);
102
+ if (attr && attr[1].trim() !== '')
103
+ return attr[1].trim();
104
+ const child = /<Version>\s*([^<]*?)\s*<\/Version>/i.exec(element);
105
+ if (child)
106
+ return child[1].trim();
107
+ return '';
108
+ }
109
+ /** Match the whole `<PackageReference>` element (either attribute order, self-close or open/close) for one id. */
110
+ function packageRefElementRegex(id) {
111
+ const escId = escapeRegExp(id);
112
+ return new RegExp(`<PackageReference\\b[^>]*?\\bInclude\\s*=\\s*"${escId}"[^>]*?(?:/>|>[\\s\\S]*?</PackageReference>)`, 'i');
113
+ }
114
+ function detectIndent(text) {
115
+ const m = text.match(/\n([ \t]*)<PackageReference\b/);
116
+ return m ? m[1] : ' ';
117
+ }
118
+ function detectEol(text) {
119
+ const crlf = (text.match(/\r\n/g) ?? []).length;
120
+ const lf = (text.match(/\n/g) ?? []).length - crlf;
121
+ return crlf > lf ? '\r\n' : '\n';
122
+ }
123
+ function renderRef(descriptor) {
124
+ // Always emit a Version: the descriptor's pin when set, else the "*" float marker. A versionless
125
+ // reference fails NuGet restore with NU1015. Byte-equal to the C# planner's AppendPackageReference.
126
+ const version = hasVersion(descriptor) ? descriptor.version : FLOAT_VERSION;
127
+ return `<PackageReference Include="${descriptor.packageId}" Version="${version}" />`;
128
+ }
129
+ /** Index of the `</ItemGroup>` closing the FIRST `<ItemGroup>` holding a `<PackageReference>`, or -1. */
130
+ function findPackageReferenceItemGroupClose(text) {
131
+ const itemGroupRe = /<ItemGroup\b[^>]*>([\s\S]*?)<\/ItemGroup>/gi;
132
+ let m;
133
+ while ((m = itemGroupRe.exec(text)) !== null) {
134
+ if (/<PackageReference\b/i.test(m[1])) {
135
+ const closeTag = '</ItemGroup>';
136
+ return m.index + m[0].length - closeTag.length;
137
+ }
138
+ }
139
+ return -1;
140
+ }
141
+ /** Append a new `<PackageReference>` for the descriptor, joining the first package ItemGroup or a fresh one. */
142
+ function appendReference(text, descriptor) {
143
+ const indent = detectIndent(text);
144
+ const eol = detectEol(text);
145
+ const element = `${indent}${renderRef(descriptor)}`;
146
+ const pkgItemGroupClose = findPackageReferenceItemGroupClose(text);
147
+ if (pkgItemGroupClose !== -1) {
148
+ // Insert before the START of the `</ItemGroup>` line, not at the `<` of `</ItemGroup>`
149
+ // itself: slicing at `pkgItemGroupClose` would absorb the closing tag's indent into the
150
+ // prefix, so the appended element would inherit that indent on top of its own and
151
+ // `</ItemGroup>` would lose its indent. Splitting at the line start keeps both aligned.
152
+ const lineStart = text.lastIndexOf('\n', pkgItemGroupClose) + 1;
153
+ return `${text.slice(0, lineStart)}${element}${eol}${text.slice(lineStart)}`;
154
+ }
155
+ const groupIndent = indent.length >= 2 ? indent.slice(0, Math.floor(indent.length / 2)) : ' ';
156
+ const newGroup = `${groupIndent}<ItemGroup>${eol}${element}${eol}${groupIndent}</ItemGroup>${eol}`;
157
+ const closeIdx = text.lastIndexOf('</Project>');
158
+ if (closeIdx === -1)
159
+ return `${text}${eol}${newGroup}`;
160
+ return `${text.slice(0, closeIdx)}${newGroup}${text.slice(closeIdx)}`;
161
+ }
162
+ /** Set the version on an existing element span, honoring whichever form it already uses (attribute, child element, or unversioned). */
163
+ function setElementVersion(element, version) {
164
+ // Existing Version="x" attribute → replace its value.
165
+ if (/\bVersion\s*=\s*"[^"]*"/i.test(element)) {
166
+ return element.replace(/\bVersion\s*=\s*"[^"]*"/i, `Version="${version}"`);
167
+ }
168
+ // Existing <Version>x</Version> child element → replace inner text (keep the child form).
169
+ if (/<Version>[\s\S]*?<\/Version>/i.test(element)) {
170
+ return element.replace(/<Version>[\s\S]*?<\/Version>/i, `<Version>${version}</Version>`);
171
+ }
172
+ // No version present → add a Version attribute to the open tag.
173
+ if (/\/>\s*$/.test(element)) {
174
+ // self-close: `<PackageReference Include="id" />` → `... Version="x" />`
175
+ return element.replace(/\s*\/>\s*$/, ` Version="${version}" />`);
176
+ }
177
+ // open/close pair with no child version: add the attribute to the open tag's first `>`.
178
+ return element.replace(/>/, ` Version="${version}">`);
179
+ }
180
+ /**
181
+ * Compute the install plan for `descriptor` against `csprojText`. Port of
182
+ * `ExtensionInstallPlanner.Plan`. Throws {@link CsprojParseError} only on a genuinely
183
+ * malformed `.csproj` (no recognizable `<Project ...>` root) — the caller maps that to
184
+ * a structured failure rather than corrupting the file.
185
+ */
186
+ export function planExtensionInstall(descriptor, csprojText) {
187
+ if (!/<Project\b[\s\S]*?>/i.test(csprojText) || !/<\/Project>/i.test(csprojText)) {
188
+ throw new CsprojParseError('The consumer .csproj is not valid XML; refusing to edit it.');
189
+ }
190
+ const elementRe = packageRefElementRegex(descriptor.packageId);
191
+ const match = csprojText.match(elementRe);
192
+ // --- No existing reference → ADD ---
193
+ if (!match) {
194
+ return {
195
+ action: 'add',
196
+ resultingCsproj: appendReference(csprojText, descriptor),
197
+ packageId: descriptor.packageId,
198
+ fromVersion: null,
199
+ toVersion: hasVersion(descriptor) ? descriptor.version : FLOAT_VERSION,
200
+ };
201
+ }
202
+ const element = match[0];
203
+ const currentVersion = readElementVersion(element);
204
+ // Descriptor pins no version → it wants a FLOATING reference (Version="*").
205
+ if (!hasVersion(descriptor)) {
206
+ // SELF-HEAL: an existing reference with NO version is NU1015-prone — upgrade it to "*".
207
+ // But NEVER downgrade a concrete consumer pin (or an existing "*") to "*": leave any
208
+ // already-versioned reference untouched (no-op), since the consumer's pin is authoritative.
209
+ if (currentVersion === '') {
210
+ const healedElement = setElementVersion(element, FLOAT_VERSION);
211
+ return {
212
+ action: 'update',
213
+ // Function replacement so any `$` in the marker is never treated as a replacement pattern.
214
+ resultingCsproj: csprojText.replace(elementRe, () => healedElement),
215
+ packageId: descriptor.packageId,
216
+ fromVersion: currentVersion,
217
+ toVersion: FLOAT_VERSION,
218
+ };
219
+ }
220
+ return {
221
+ action: 'noop',
222
+ resultingCsproj: csprojText,
223
+ packageId: descriptor.packageId,
224
+ fromVersion: currentVersion,
225
+ toVersion: null,
226
+ };
227
+ }
228
+ const target = descriptor.version;
229
+ const needsBump = currentVersion === '' || compareVersions(target, currentVersion) > 0;
230
+ if (!needsBump) {
231
+ return {
232
+ action: 'noop',
233
+ resultingCsproj: csprojText,
234
+ packageId: descriptor.packageId,
235
+ fromVersion: currentVersion,
236
+ toVersion: target,
237
+ };
238
+ }
239
+ const updatedElement = setElementVersion(element, target);
240
+ return {
241
+ action: 'update',
242
+ // Function replacement so any `$` in the version is never treated as a replacement pattern.
243
+ resultingCsproj: csprojText.replace(elementRe, () => updatedElement),
244
+ packageId: descriptor.packageId,
245
+ fromVersion: currentVersion,
246
+ toVersion: target,
247
+ };
248
+ }
249
+ //# sourceMappingURL=extension-install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-install.js","sourceRoot":"","sources":["../../src/utils/extension-install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /** One tool a catalog extension contributes — mirrors the JSON `tools[]` entry. */
2
+ export interface ExtensionTool {
3
+ readonly name: string;
4
+ readonly description: string;
5
+ }
6
+ /**
7
+ * The third-party Godot addon a CLASS-B extension wraps — mirrors the JSON
8
+ * `addonRequired` block. Class-A extensions (which wrap a BUILT-IN Godot feature)
9
+ * OMIT this entirely (`addonRequired` is absent / `undefined`). When present it is
10
+ * pure presentation metadata so the dock/app/CLI can surface "requires the <name>
11
+ * addon" + a link; it does NOT affect install logic (the package is still installed
12
+ * by `packageId` alone — the addon is the consumer's own runtime responsibility).
13
+ * `name` is the anchor; `assetLibId` (the Godot AssetLib id, stored as a string),
14
+ * `repo`, and `license` are optional.
15
+ */
16
+ export interface ExtensionAddonRequirement {
17
+ readonly name: string;
18
+ readonly assetLibId: string | null;
19
+ readonly repo: string | null;
20
+ readonly license: string | null;
21
+ }
22
+ /**
23
+ * One installable extension — the CLI analog of the C# `GodotExtensionDescriptor`.
24
+ * `packageId` is the INSTALL IDENTITY (the `<PackageReference Include="...">`).
25
+ * `version` is `null` for a floating (unpinned) reference.
26
+ * `addonRequired` is present ONLY for CLASS-B (addon-dependent) extensions; Class-A
27
+ * entries omit it.
28
+ */
29
+ export interface ExtensionDescriptor {
30
+ readonly name: string;
31
+ readonly description: string;
32
+ readonly packageId: string;
33
+ readonly version: string | null;
34
+ readonly gitUrl: string | null;
35
+ readonly tools: readonly ExtensionTool[];
36
+ readonly addonRequired?: ExtensionAddonRequirement | null;
37
+ }
38
+ /**
39
+ * The extension catalog, single-sourced from `addons/godot_mcp/extensions.catalog.json`.
40
+ * Ships EMPTY until the first Godot-MCP extension package is published on nuget.org —
41
+ * `install-extension <id>` then reports "unknown extension" for every id, which is the
42
+ * correct behavior (there is nothing to install yet). The parity test keeps this in
43
+ * lockstep with the JSON so adding an entry there forces an update here.
44
+ */
45
+ export declare const EXTENSIONS_CATALOG: readonly ExtensionDescriptor[];
46
+ /** True when a descriptor carries a concrete version pin (drives the up-to-date / update decision). */
47
+ export declare function hasVersion(descriptor: ExtensionDescriptor): boolean;
48
+ /**
49
+ * Resolve a user-supplied `<id>` to a catalog descriptor. Matches by `packageId`
50
+ * first (ordinal-ignore-case, like NuGet's case-insensitive ids — the install
51
+ * identity), then falls back to an exact case-insensitive `name` match for
52
+ * convenience. Returns `null` when absent or `id` is empty.
53
+ */
54
+ export declare function findExtension(id: string | undefined | null, catalog?: readonly ExtensionDescriptor[]): ExtensionDescriptor | null;
@@ -0,0 +1,222 @@
1
+ // The CLI's typed mirror of the SHARED extension catalog — the single source of
2
+ // truth `addons/godot_mcp/extensions.catalog.json` (see that file's sibling
3
+ // `extensions.catalog.md`). It is the CLI half of the "one catalog consumed by the
4
+ // dock, the CLI, and the app" contract: the dock parses the JSON via an embedded
5
+ // resource (C# `GodotExtensionCatalog`); the CLI mirrors it here so the published
6
+ // npm package stays self-contained (no runtime `../addons` dependency).
7
+ //
8
+ // SINGLE SOURCE OF TRUTH: this constant MUST stay byte-equivalent to the JSON. The
9
+ // parity test `cli/tests/extensions-catalog-parity.test.ts` reads the addon JSON and
10
+ // FAILS the build if this mirror drifts — exactly the discipline `addon-deps.ts` /
11
+ // `addon-deps-parity.test.ts` use for the NuGet pins. Adding an extension =
12
+ // appending an entry to BOTH the JSON and this array (the test enforces it).
13
+ //
14
+ // No top-level side effects; pure data + pure lookups only.
15
+ /**
16
+ * The extension catalog, single-sourced from `addons/godot_mcp/extensions.catalog.json`.
17
+ * Ships EMPTY until the first Godot-MCP extension package is published on nuget.org —
18
+ * `install-extension <id>` then reports "unknown extension" for every id, which is the
19
+ * correct behavior (there is nothing to install yet). The parity test keeps this in
20
+ * lockstep with the JSON so adding an entry there forces an update here.
21
+ */
22
+ export const EXTENSIONS_CATALOG = [
23
+ {
24
+ name: 'Particles Tools',
25
+ description: 'AI MCP tools for Godot GpuParticles (2D & 3D): create, configure, start/stop, and inspect emitters.',
26
+ packageId: 'com.IvanMurzak.Godot.MCP.Particles',
27
+ version: null,
28
+ gitUrl: 'https://github.com/IvanMurzak/Godot-AI-Particles',
29
+ tools: [
30
+ { name: 'particles-defaults', description: 'Return the recommended starter config for a 2D/3D emitter.' },
31
+ { name: 'particles-create', description: 'Create a GpuParticles2D/GpuParticles3D node in the edited scene.' },
32
+ { name: 'particles-configure', description: "Update an emitter's scalar properties (clamped to valid ranges)." },
33
+ { name: 'particles-set-emitting', description: 'Start or stop emission, optionally restarting first.' },
34
+ { name: 'particles-get', description: "Read an emitter's scalar config (read-only)." },
35
+ ],
36
+ },
37
+ {
38
+ name: 'Tilemap Tools',
39
+ description: 'AI MCP tools for Godot TileMapLayer (4.3+): create layers, assign tilesets, set/erase cells, and inspect used cells.',
40
+ packageId: 'com.IvanMurzak.Godot.MCP.Tilemap',
41
+ version: null,
42
+ gitUrl: 'https://github.com/IvanMurzak/Godot-AI-Tilemap',
43
+ tools: [
44
+ { name: 'tilemap-create', description: 'Create a TileMapLayer node in the currently edited Godot scene.' },
45
+ { name: 'tilemap-set-tileset', description: 'Assign a TileSet resource to an existing TileMapLayer.' },
46
+ { name: 'tilemap-set-cell', description: 'Set a single cell on a TileMapLayer (by map + atlas coords).' },
47
+ { name: 'tilemap-erase-cell', description: 'Erase a single cell on a TileMapLayer (set it back to empty).' },
48
+ { name: 'tilemap-get-used-cells', description: 'List the used (non-empty) cells of a TileMapLayer (read-only).' },
49
+ { name: 'tilemap-clear', description: 'Clear all cells on a TileMapLayer (the assigned TileSet is kept).' },
50
+ ],
51
+ },
52
+ {
53
+ name: 'Navigation Tools',
54
+ description: 'AI MCP tools for Godot navigation (2D & 3D): create regions, agents, and links, set region meshes, configure agents, and inspect navigation nodes.',
55
+ packageId: 'com.IvanMurzak.Godot.MCP.Navigation',
56
+ version: null,
57
+ gitUrl: 'https://github.com/IvanMurzak/Godot-AI-Navigation',
58
+ tools: [
59
+ { name: 'navigation-defaults', description: 'Return the recommended starter config (radius, distances, max speed) for a 2D/3D NavigationAgent.' },
60
+ { name: 'navigation-region-create', description: 'Create a NavigationRegion2D/NavigationRegion3D node (a navigable area) in the edited scene.' },
61
+ { name: 'navigation-region-set-mesh', description: "Assign a region's navigation resource (NavigationPolygon in 2D, NavigationMesh in 3D)." },
62
+ { name: 'navigation-agent-create', description: 'Create a NavigationAgent2D/NavigationAgent3D node (pathfinding + avoidance) in the edited scene.' },
63
+ { name: 'navigation-agent-configure', description: "Update a NavigationAgent's scalar properties (clamped to valid ranges)." },
64
+ { name: 'navigation-link-create', description: 'Create a NavigationLink2D/NavigationLink3D node (an off-mesh connection between two points).' },
65
+ { name: 'navigation-get', description: "Read a navigation node's scalar config (read-only)." },
66
+ ],
67
+ },
68
+ {
69
+ name: 'Animation Tools',
70
+ description: 'AI MCP tools for Godot AnimationPlayer: create players, libraries, and animations, add tracks, insert keyframes, and inspect them.',
71
+ packageId: 'com.IvanMurzak.Godot.MCP.Animation',
72
+ version: null,
73
+ gitUrl: 'https://github.com/IvanMurzak/Godot-AI-Animation',
74
+ tools: [
75
+ { name: 'animation-defaults', description: 'Return the recommended starter config (length, loop mode) for a new animation.' },
76
+ { name: 'animation-player-create', description: 'Create an AnimationPlayer node in the currently edited Godot scene.' },
77
+ { name: 'animation-library-add', description: 'Add a new empty AnimationLibrary to an existing AnimationPlayer.' },
78
+ { name: 'animation-create', description: "Create an Animation in an AnimationPlayer's library (auto-created when missing)." },
79
+ { name: 'animation-add-track', description: 'Add a value or 3D transform track to an existing Animation.' },
80
+ { name: 'animation-insert-key', description: 'Insert a keyframe on an animation track.' },
81
+ { name: 'animation-get', description: "Read an AnimationPlayer's libraries, animations, and a clip's tracks (read-only)." },
82
+ ],
83
+ },
84
+ {
85
+ name: 'CSG Tools',
86
+ description: 'AI MCP tools for Godot CSG (Constructive Solid Geometry): create box/sphere/cylinder primitives and combiners, set boolean operations, and inspect them.',
87
+ packageId: 'com.IvanMurzak.Godot.MCP.CSG',
88
+ version: null,
89
+ gitUrl: 'https://github.com/IvanMurzak/Godot-AI-CSG',
90
+ tools: [
91
+ { name: 'csg-defaults', description: 'Return the recommended starter config (size / radius / height / segments) for a CSG node of the requested kind.' },
92
+ { name: 'csg-box-create', description: 'Create a CsgBox3D primitive in the currently edited Godot scene.' },
93
+ { name: 'csg-sphere-create', description: 'Create a CsgSphere3D primitive in the currently edited Godot scene.' },
94
+ { name: 'csg-cylinder-create', description: 'Create a CsgCylinder3D primitive in the currently edited Godot scene.' },
95
+ { name: 'csg-combiner-create', description: 'Create a CsgCombiner3D container that groups child CSG shapes for boolean ops.' },
96
+ { name: 'csg-set-operation', description: "Set an existing CSG node's boolean operation (Union / Intersection / Subtraction)." },
97
+ { name: 'csg-get', description: "Read a CSG node's scalar config (read-only)." },
98
+ ],
99
+ },
100
+ {
101
+ name: 'GridMap Tools',
102
+ description: 'AI MCP tools for Godot GridMap (3D tile-based maps): create, set/clear cells, assign a MeshLibrary, and inspect.',
103
+ packageId: 'com.IvanMurzak.Godot.MCP.GridMap',
104
+ version: null,
105
+ gitUrl: 'https://github.com/IvanMurzak/Godot-AI-GridMap',
106
+ tools: [
107
+ { name: 'gridmap-defaults', description: 'Return the recommended starter configuration for a new GridMap node.' },
108
+ { name: 'gridmap-create', description: 'Create a GridMap node in the currently edited Godot scene.' },
109
+ { name: 'gridmap-set-mesh-library', description: 'Assign a MeshLibrary resource to an existing GridMap node.' },
110
+ { name: 'gridmap-set-cell', description: 'Set a single cell of a GridMap to a MeshLibrary item.' },
111
+ { name: 'gridmap-clear-cell', description: 'Clear a single cell of a GridMap.' },
112
+ { name: 'gridmap-clear', description: 'Clear all cells of a GridMap.' },
113
+ { name: 'gridmap-get', description: "Read a GridMap's scalar config (read-only)." },
114
+ ],
115
+ },
116
+ {
117
+ name: 'PhantomCamera Tools',
118
+ description: 'AI MCP tools for the Godot Phantom Camera addon (Cinemachine-style virtual cameras): create hosts and cameras, set follow/look-at targets and priority, and inspect them.',
119
+ packageId: 'com.IvanMurzak.Godot.MCP.PhantomCamera',
120
+ version: null,
121
+ gitUrl: 'https://github.com/IvanMurzak/Godot-AI-PhantomCamera',
122
+ tools: [
123
+ { name: 'phantomcamera-defaults', description: 'Return the recommended starter config (priority, follow/look-at mode, damping) for a Phantom Camera.' },
124
+ { name: 'phantomcamera-host-create', description: 'Ensure a PhantomCameraHost exists under a Camera3D in the edited scene (required by the addon).' },
125
+ { name: 'phantomcamera-create', description: 'Create a PhantomCamera3D node (a virtual camera) in the currently edited Godot scene.' },
126
+ { name: 'phantomcamera-set-follow', description: "Set an existing PhantomCamera3D's follow mode and/or follow target." },
127
+ { name: 'phantomcamera-set-look-at', description: "Set an existing PhantomCamera3D's look-at mode and/or look-at target." },
128
+ { name: 'phantomcamera-set-priority', description: "Set an existing PhantomCamera3D's priority (higher wins; raising it switches the active camera)." },
129
+ { name: 'phantomcamera-get', description: "Read an existing PhantomCamera3D's scalar config (read-only)." },
130
+ ],
131
+ addonRequired: {
132
+ name: 'Phantom Camera',
133
+ assetLibId: '1822',
134
+ repo: 'ramokz/phantom-camera',
135
+ license: 'MIT',
136
+ },
137
+ },
138
+ {
139
+ name: 'Beehave Tools',
140
+ description: 'AI MCP tools for the Godot Beehave addon (behaviour-tree AI): scaffold a tree root, add composites, decorators, and leaf placeholders, and inspect them.',
141
+ packageId: 'com.IvanMurzak.Godot.MCP.Beehave',
142
+ version: null,
143
+ gitUrl: 'https://github.com/IvanMurzak/Godot-AI-Beehave',
144
+ tools: [
145
+ { name: 'beehave-defaults', description: 'Return the recommended starter skeleton (root, tick rate, a composite, and leaf placeholders) for a Beehave behaviour tree.' },
146
+ { name: 'beehave-tree-create', description: 'Create a BeehaveTree behaviour-tree root in the currently edited Godot scene.' },
147
+ { name: 'beehave-add-composite', description: 'Add a Selector/Sequence composite under an existing tree or composite.' },
148
+ { name: 'beehave-add-decorator', description: 'Add an Inverter/Limiter decorator under an existing tree or composite.' },
149
+ { name: 'beehave-add-leaf', description: 'Add an Action/Condition leaf placeholder under a composite or decorator.' },
150
+ { name: 'beehave-get', description: "Read a BeehaveTree's scalar config and dump its tree structure (read-only)." },
151
+ ],
152
+ addonRequired: {
153
+ name: 'Beehave',
154
+ assetLibId: '1349',
155
+ repo: 'bitbrain/beehave',
156
+ license: 'MIT',
157
+ },
158
+ },
159
+ {
160
+ name: 'Dialogic Tools',
161
+ description: 'AI MCP tools for the Godot Dialogic addon (dialogue / visual novels): create timeline and character resources, append text events, and inspect them.',
162
+ packageId: 'com.IvanMurzak.Godot.MCP.Dialogic',
163
+ version: null,
164
+ gitUrl: 'https://github.com/IvanMurzak/Godot-AI-Dialogic',
165
+ tools: [
166
+ { name: 'dialogic-defaults', description: 'Return the recommended starter timeline and character config for Dialogic authoring.' },
167
+ { name: 'dialogic-timeline-create', description: 'Create a Dialogic timeline resource (.dtl), seeded with a first text event.' },
168
+ { name: 'dialogic-character-create', description: 'Create a Dialogic character resource (.dch) with a display name and color.' },
169
+ { name: 'dialogic-timeline-add-text', description: 'Append a text event (optionally with a speaker) to an existing Dialogic timeline (.dtl).' },
170
+ { name: 'dialogic-get', description: "Read a Dialogic timeline (.dtl) or character (.dch) resource's config (read-only)." },
171
+ ],
172
+ addonRequired: {
173
+ name: 'Dialogic',
174
+ assetLibId: null,
175
+ repo: 'dialogic-godot/dialogic',
176
+ license: 'MIT',
177
+ },
178
+ },
179
+ {
180
+ name: 'Terrain3D Tools',
181
+ description: 'AI MCP tools for the Godot Terrain3D addon (TokisanGames heightmap terrain): create terrains, set the data directory, region size, and material, and inspect them.',
182
+ packageId: 'com.IvanMurzak.Godot.MCP.Terrain3D',
183
+ version: null,
184
+ gitUrl: 'https://github.com/IvanMurzak/Godot-AI-Terrain3D',
185
+ tools: [
186
+ { name: 'terrain3d-defaults', description: 'Return the recommended starter config (region size, mesh LODs, mesh size, vertex spacing, data directory) for a Terrain3D node.' },
187
+ { name: 'terrain3d-create', description: 'Create a Terrain3D node in the currently edited Godot scene (requires the Terrain3D addon).' },
188
+ { name: 'terrain3d-set-data-directory', description: "Set an existing Terrain3D node's res:// data directory (where region data persists)." },
189
+ { name: 'terrain3d-set-region-size', description: "Set an existing Terrain3D node's region size (snapped to a valid Terrain3D size)." },
190
+ { name: 'terrain3d-set-material', description: 'Assign a Terrain3DMaterial to an existing Terrain3D node (created when missing).' },
191
+ { name: 'terrain3d-get', description: "Read a Terrain3D node's scalar config (read-only)." },
192
+ ],
193
+ addonRequired: {
194
+ name: 'Terrain3D',
195
+ assetLibId: '3892',
196
+ repo: 'TokisanGames/Terrain3D',
197
+ license: 'MIT',
198
+ },
199
+ },
200
+ ];
201
+ /** True when a descriptor carries a concrete version pin (drives the up-to-date / update decision). */
202
+ export function hasVersion(descriptor) {
203
+ return descriptor.version !== null && descriptor.version.trim() !== '';
204
+ }
205
+ /**
206
+ * Resolve a user-supplied `<id>` to a catalog descriptor. Matches by `packageId`
207
+ * first (ordinal-ignore-case, like NuGet's case-insensitive ids — the install
208
+ * identity), then falls back to an exact case-insensitive `name` match for
209
+ * convenience. Returns `null` when absent or `id` is empty.
210
+ */
211
+ export function findExtension(id, catalog = EXTENSIONS_CATALOG) {
212
+ if (id === undefined || id === null)
213
+ return null;
214
+ const needle = id.trim();
215
+ if (needle === '')
216
+ return null;
217
+ const byPackageId = catalog.find((d) => d.packageId.toLowerCase() === needle.toLowerCase());
218
+ if (byPackageId)
219
+ return byPackageId;
220
+ return catalog.find((d) => d.name.toLowerCase() === needle.toLowerCase()) ?? null;
221
+ }
222
+ //# sourceMappingURL=extensions-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extensions-catalog.js","sourceRoot":"","sources":["../../src/utils/extensions-catalog.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "godot-cli",
3
- "version": "0.13.3",
3
+ "version": "0.15.0",
4
4
  "description": "Cross-platform CLI tool for Godot-MCP (Skills & MCP). Resolves and launches the Godot editor with MCP connection env vars, runs MCP/system tools over HTTP, probes server health, configures AI agents (Claude Code, Cursor, VS Code, …), and enables/disables the godot_mcp addon. Works with Claude Code, Cursor, Copilot, and any MCP client.",
5
5
  "type": "module",
6
6
  "main": "dist/lib.js",