@godot-mcp/cli 0.0.0 → 0.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 (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -2
  3. package/dist/bin.d.ts +3 -0
  4. package/dist/bin.d.ts.map +1 -0
  5. package/dist/bin.js +88 -0
  6. package/dist/bin.js.map +1 -0
  7. package/dist/commands/connect.d.ts +7 -0
  8. package/dist/commands/connect.d.ts.map +1 -0
  9. package/dist/commands/connect.js +71 -0
  10. package/dist/commands/connect.js.map +1 -0
  11. package/dist/commands/disable.d.ts +2 -0
  12. package/dist/commands/disable.d.ts.map +1 -0
  13. package/dist/commands/disable.js +5 -0
  14. package/dist/commands/disable.js.map +1 -0
  15. package/dist/commands/doctor.d.ts +3 -0
  16. package/dist/commands/doctor.d.ts.map +1 -0
  17. package/dist/commands/doctor.js +5 -0
  18. package/dist/commands/doctor.js.map +1 -0
  19. package/dist/commands/editor.d.ts +7 -0
  20. package/dist/commands/editor.d.ts.map +1 -0
  21. package/dist/commands/editor.js +84 -0
  22. package/dist/commands/editor.js.map +1 -0
  23. package/dist/commands/init.d.ts +3 -0
  24. package/dist/commands/init.d.ts.map +1 -0
  25. package/dist/commands/init.js +9 -0
  26. package/dist/commands/init.js.map +1 -0
  27. package/dist/commands/uninstall.d.ts +2 -0
  28. package/dist/commands/uninstall.d.ts.map +1 -0
  29. package/dist/commands/uninstall.js +5 -0
  30. package/dist/commands/uninstall.js.map +1 -0
  31. package/dist/commands/unsafeFixture.d.ts +5 -0
  32. package/dist/commands/unsafeFixture.d.ts.map +1 -0
  33. package/dist/commands/unsafeFixture.js +14 -0
  34. package/dist/commands/unsafeFixture.js.map +1 -0
  35. package/dist/commands/upgrade.d.ts +2 -0
  36. package/dist/commands/upgrade.d.ts.map +1 -0
  37. package/dist/commands/upgrade.js +5 -0
  38. package/dist/commands/upgrade.js.map +1 -0
  39. package/dist/index.d.ts +12 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +12 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/install/addonInstaller.d.ts +10 -0
  44. package/dist/install/addonInstaller.d.ts.map +1 -0
  45. package/dist/install/addonInstaller.js +225 -0
  46. package/dist/install/addonInstaller.js.map +1 -0
  47. package/dist/install/addonManifest.d.ts +28 -0
  48. package/dist/install/addonManifest.d.ts.map +1 -0
  49. package/dist/install/addonManifest.js +95 -0
  50. package/dist/install/addonManifest.js.map +1 -0
  51. package/dist/install/doctor.d.ts +11 -0
  52. package/dist/install/doctor.d.ts.map +1 -0
  53. package/dist/install/doctor.js +86 -0
  54. package/dist/install/doctor.js.map +1 -0
  55. package/dist/install/pluginState.d.ts +12 -0
  56. package/dist/install/pluginState.d.ts.map +1 -0
  57. package/dist/install/pluginState.js +95 -0
  58. package/dist/install/pluginState.js.map +1 -0
  59. package/dist/runtime/createRuntime.d.ts +31 -0
  60. package/dist/runtime/createRuntime.d.ts.map +1 -0
  61. package/dist/runtime/createRuntime.js +301 -0
  62. package/dist/runtime/createRuntime.js.map +1 -0
  63. package/godot/plugin_state.gd +18 -0
  64. package/package.json +31 -6
  65. package/index.js +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,mCAAmC,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACtH,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,GAEf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,SAAS,EAAuC,MAAM,qBAAqB,CAAC;AACrF,OAAO,EACL,eAAe,EACf,aAAa,GAEd,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,4BAA4B,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type InstallManifest } from "./addonManifest.js";
2
+ export interface InstallAddonResult {
3
+ projectRoot: string;
4
+ manifest: InstallManifest;
5
+ warnings?: string[];
6
+ }
7
+ export declare function installAddon(projectInput: string, sourceInput: string): Promise<InstallAddonResult>;
8
+ export declare function upgradeAddon(projectInput: string, sourceInput: string): Promise<InstallAddonResult>;
9
+ export declare function uninstallAddon(projectInput: string): Promise<void>;
10
+ //# sourceMappingURL=addonInstaller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addonInstaller.d.ts","sourceRoot":"","sources":["../../src/install/addonInstaller.ts"],"names":[],"mappings":"AAqBA,OAAO,EAKL,KAAK,eAAe,EAGrB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AA8FD,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CA8C7B;AAED,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CAwD7B;AAED,wBAAsB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBxE"}
@@ -0,0 +1,225 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { access, copyFile, lstat, mkdir, readFile, readdir, rename, rm, writeFile, } from "node:fs/promises";
3
+ import { dirname, join, relative, resolve } from "node:path";
4
+ import { createProjectConfig, discoverProject, GodotMcpException, } from "@godot-mcp/control-plane";
5
+ import { PRODUCT_VERSION } from "@godot-mcp/protocol";
6
+ import { hashFileEntries, manifestPath, readInstallManifest, sha256, writeInstallManifest, } from "./addonManifest.js";
7
+ function conflict(message) {
8
+ return new GodotMcpException({
9
+ code: "CONFLICT",
10
+ message,
11
+ retryable: false,
12
+ correlationId: randomUUID(),
13
+ partialEffects: false,
14
+ rollback: "not_attempted",
15
+ });
16
+ }
17
+ async function exists(path) {
18
+ try {
19
+ await access(path);
20
+ return true;
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ async function sourceFiles(root) {
27
+ const files = [];
28
+ async function visit(directory) {
29
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
30
+ const absolute = join(directory, entry.name);
31
+ if (entry.isDirectory()) {
32
+ await visit(absolute);
33
+ }
34
+ else if (entry.isFile()) {
35
+ files.push(relative(root, absolute));
36
+ }
37
+ else {
38
+ throw conflict(`Addon source contains a non-regular entry: ${absolute}`);
39
+ }
40
+ }
41
+ }
42
+ await visit(root);
43
+ return files.sort((left, right) => left.localeCompare(right));
44
+ }
45
+ async function installedTreeFiles(root) {
46
+ if (!(await exists(root)))
47
+ return [];
48
+ return sourceFiles(root);
49
+ }
50
+ async function atomicWrite(path, contents) {
51
+ const temporary = `${path}.godot-mcp-${randomUUID()}`;
52
+ await writeFile(temporary, contents);
53
+ await rename(temporary, path);
54
+ }
55
+ async function verifyInstalledTree(projectRoot, manifest) {
56
+ const destinationRoot = join(projectRoot, "addons/godot_mcp");
57
+ const expectedRelative = manifest.files.map((file) => file.relativePath.slice("addons/godot_mcp/".length));
58
+ const actualRelative = await installedTreeFiles(destinationRoot);
59
+ if (JSON.stringify(actualRelative) !== JSON.stringify(expectedRelative)) {
60
+ throw conflict("Installed addon tree contains missing or untracked files");
61
+ }
62
+ for (const file of manifest.files) {
63
+ const current = await readFile(join(projectRoot, file.relativePath));
64
+ if (sha256(current) !== file.sha256) {
65
+ throw conflict(`Installed addon file was modified: ${file.relativePath}`);
66
+ }
67
+ }
68
+ }
69
+ async function stageAddon(sourceRoot, temporaryRoot) {
70
+ const sourceMetadata = await lstat(sourceRoot);
71
+ if (!sourceMetadata.isDirectory() || sourceMetadata.isSymbolicLink()) {
72
+ throw conflict("Addon source must be a regular directory");
73
+ }
74
+ const files = await sourceFiles(sourceRoot);
75
+ if (files.length === 0)
76
+ throw conflict("Addon source contains no files");
77
+ await mkdir(temporaryRoot, { recursive: false, mode: 0o700 });
78
+ const entries = [];
79
+ for (const sourceRelativePath of files) {
80
+ const sourcePath = join(sourceRoot, sourceRelativePath);
81
+ const temporaryPath = join(temporaryRoot, sourceRelativePath);
82
+ await mkdir(dirname(temporaryPath), { recursive: true, mode: 0o700 });
83
+ await copyFile(sourcePath, temporaryPath);
84
+ const digest = sha256(await readFile(temporaryPath));
85
+ if (digest !== sha256(await readFile(sourcePath))) {
86
+ throw conflict(`Copied addon file failed hash verification: ${sourceRelativePath}`);
87
+ }
88
+ entries.push({
89
+ relativePath: join("addons/godot_mcp", sourceRelativePath).replaceAll("\\", "/"),
90
+ sha256: digest,
91
+ });
92
+ }
93
+ return entries.sort((left, right) => left.relativePath.localeCompare(right.relativePath));
94
+ }
95
+ export async function installAddon(projectInput, sourceInput) {
96
+ const project = await discoverProject(projectInput);
97
+ const sourceRoot = resolve(sourceInput);
98
+ const destinationRoot = join(project.rootRealPath, "addons/godot_mcp");
99
+ const addonsRoot = dirname(destinationRoot);
100
+ const temporaryRoot = join(addonsRoot, `.godot_mcp.tmp-${randomUUID()}`);
101
+ const configPath = join(project.rootRealPath, ".godot-mcp.json");
102
+ if (await exists(destinationRoot))
103
+ throw conflict("Godot MCP addon destination already exists");
104
+ if (await exists(manifestPath(project.rootRealPath)))
105
+ throw conflict("Godot MCP install manifest already exists");
106
+ const projectPreimage = await readFile(project.projectFileRealPath);
107
+ const configCreated = !(await exists(configPath));
108
+ await createProjectConfig(project.rootRealPath);
109
+ const configContents = await readFile(configPath);
110
+ try {
111
+ await mkdir(addonsRoot, { recursive: true, mode: 0o700 });
112
+ const entries = await stageAddon(sourceRoot, temporaryRoot);
113
+ await rename(temporaryRoot, destinationRoot);
114
+ const projectDigest = sha256(projectPreimage);
115
+ const manifest = {
116
+ schemaVersion: 1,
117
+ productVersion: PRODUCT_VERSION,
118
+ installedAt: new Date().toISOString(),
119
+ manifestSha256: hashFileEntries(entries),
120
+ files: entries,
121
+ projectFile: {
122
+ preimageBase64: projectPreimage.toString("base64"),
123
+ preimageSha256: projectDigest,
124
+ postimageSha256: projectDigest,
125
+ },
126
+ projectConfig: { created: configCreated, sha256: sha256(configContents) },
127
+ };
128
+ await writeInstallManifest(project.rootRealPath, manifest);
129
+ return { projectRoot: project.rootRealPath, manifest };
130
+ }
131
+ catch (error) {
132
+ await rm(temporaryRoot, { force: true, recursive: true });
133
+ await rm(destinationRoot, { force: true, recursive: true });
134
+ if (configCreated && (await exists(configPath))) {
135
+ const currentConfig = await readFile(configPath);
136
+ if (sha256(currentConfig) === sha256(configContents))
137
+ await rm(configPath, { force: true });
138
+ }
139
+ throw error;
140
+ }
141
+ }
142
+ export async function upgradeAddon(projectInput, sourceInput) {
143
+ const project = await discoverProject(projectInput);
144
+ const oldManifest = await readInstallManifest(project.rootRealPath).catch(() => {
145
+ throw conflict("Godot MCP install manifest is missing or invalid");
146
+ });
147
+ await verifyInstalledTree(project.rootRealPath, oldManifest);
148
+ const projectPath = join(project.rootRealPath, "project.godot");
149
+ const configPath = join(project.rootRealPath, ".godot-mcp.json");
150
+ if (sha256(await readFile(projectPath)) !== oldManifest.projectFile.postimageSha256) {
151
+ throw conflict("project.godot changed independently after Godot MCP installation");
152
+ }
153
+ if (sha256(await readFile(configPath)) !== oldManifest.projectConfig.sha256) {
154
+ throw conflict(".godot-mcp.json changed independently after Godot MCP installation");
155
+ }
156
+ const addonsRoot = join(project.rootRealPath, "addons");
157
+ const destinationRoot = join(addonsRoot, "godot_mcp");
158
+ const transactionId = randomUUID();
159
+ const temporaryRoot = join(addonsRoot, `.godot_mcp.upgrade-${transactionId}`);
160
+ const backupRoot = join(addonsRoot, `.godot_mcp.rollback-${transactionId}`);
161
+ let switched = false;
162
+ let manifest;
163
+ try {
164
+ const entries = await stageAddon(resolve(sourceInput), temporaryRoot);
165
+ manifest = {
166
+ ...oldManifest,
167
+ productVersion: PRODUCT_VERSION,
168
+ installedAt: new Date().toISOString(),
169
+ manifestSha256: hashFileEntries(entries),
170
+ files: entries,
171
+ };
172
+ await rename(destinationRoot, backupRoot);
173
+ try {
174
+ await rename(temporaryRoot, destinationRoot);
175
+ }
176
+ catch (error) {
177
+ await rename(backupRoot, destinationRoot);
178
+ throw error;
179
+ }
180
+ switched = true;
181
+ await writeInstallManifest(project.rootRealPath, manifest);
182
+ }
183
+ catch (error) {
184
+ await rm(temporaryRoot, { recursive: true, force: true });
185
+ if (switched) {
186
+ await rm(destinationRoot, { recursive: true, force: true });
187
+ await rename(backupRoot, destinationRoot);
188
+ await writeInstallManifest(project.rootRealPath, oldManifest);
189
+ }
190
+ throw error;
191
+ }
192
+ try {
193
+ await rm(backupRoot, { recursive: true });
194
+ return { projectRoot: project.rootRealPath, manifest };
195
+ }
196
+ catch {
197
+ return { projectRoot: project.rootRealPath, manifest, warnings: [`Committed upgrade retained rollback residue: ${backupRoot}`] };
198
+ }
199
+ }
200
+ export async function uninstallAddon(projectInput) {
201
+ const project = await discoverProject(projectInput);
202
+ let manifest;
203
+ try {
204
+ manifest = await readInstallManifest(project.rootRealPath);
205
+ }
206
+ catch {
207
+ throw conflict("Godot MCP install manifest is missing or invalid");
208
+ }
209
+ const destinationRoot = join(project.rootRealPath, "addons/godot_mcp");
210
+ await verifyInstalledTree(project.rootRealPath, manifest);
211
+ const projectPath = join(project.rootRealPath, "project.godot");
212
+ if (sha256(await readFile(projectPath)) !== manifest.projectFile.postimageSha256) {
213
+ throw conflict("project.godot changed independently after Godot MCP installation");
214
+ }
215
+ const configPath = join(project.rootRealPath, ".godot-mcp.json");
216
+ if (sha256(await readFile(configPath)) !== manifest.projectConfig.sha256) {
217
+ throw conflict(".godot-mcp.json changed independently after Godot MCP installation");
218
+ }
219
+ await rm(destinationRoot, { recursive: true });
220
+ await atomicWrite(projectPath, Buffer.from(manifest.projectFile.preimageBase64, "base64"));
221
+ if (manifest.projectConfig.created)
222
+ await rm(configPath);
223
+ await rm(manifestPath(project.rootRealPath));
224
+ }
225
+ //# sourceMappingURL=addonInstaller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addonInstaller.js","sourceRoot":"","sources":["../../src/install/addonInstaller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export interface InstalledFile {
2
+ relativePath: string;
3
+ sha256: string;
4
+ }
5
+ export interface InstallManifest {
6
+ schemaVersion: 1;
7
+ productVersion: string;
8
+ installedAt: string;
9
+ manifestSha256: string;
10
+ files: InstalledFile[];
11
+ projectFile: {
12
+ preimageBase64: string;
13
+ preimageSha256: string;
14
+ postimageSha256: string;
15
+ };
16
+ projectConfig: {
17
+ created: boolean;
18
+ sha256: string;
19
+ };
20
+ }
21
+ export declare function sha256(value: Uint8Array | string): string;
22
+ export declare function manifestPath(projectRoot: string): string;
23
+ export declare function hashFileEntries(files: InstalledFile[]): string;
24
+ export declare function parseInstallManifest(value: unknown): InstallManifest;
25
+ export declare function readInstallManifest(projectRoot: string): Promise<InstallManifest>;
26
+ export declare function writeInstallManifest(projectRoot: string, manifest: InstallManifest): Promise<void>;
27
+ export declare function updateProjectPostimage(projectRoot: string): Promise<void>;
28
+ //# sourceMappingURL=addonManifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addonManifest.d.ts","sourceRoot":"","sources":["../../src/install/addonManifest.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,CAAC,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,WAAW,EAAE;QACX,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,aAAa,EAAE;QACb,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAYD,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,MAAM,CAE9D;AAgBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAwCpE;AAED,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAEvF;AAED,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,wBAAsB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/E"}
@@ -0,0 +1,95 @@
1
+ import { createHash } from "node:crypto";
2
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ import { canonicalJson, PRODUCT_VERSION } from "@godot-mcp/protocol";
5
+ function supportedManifestVersion(value) {
6
+ if (typeof value !== "string" || !/^\d+\.\d+\.\d+$/.test(value))
7
+ return false;
8
+ const parsed = value.split(".").map(Number);
9
+ const current = PRODUCT_VERSION.split(".").map(Number);
10
+ for (let index = 0; index < 3; index += 1) {
11
+ if (parsed[index] < current[index])
12
+ return true;
13
+ if (parsed[index] > current[index])
14
+ return false;
15
+ }
16
+ return true;
17
+ }
18
+ export function sha256(value) {
19
+ return createHash("sha256").update(value).digest("hex");
20
+ }
21
+ export function manifestPath(projectRoot) {
22
+ return join(projectRoot, ".godot/godot-mcp/install-manifest.json");
23
+ }
24
+ export function hashFileEntries(files) {
25
+ return sha256(canonicalJson(files));
26
+ }
27
+ function isInstalledFile(value) {
28
+ if (typeof value !== "object" || value === null)
29
+ return false;
30
+ const record = value;
31
+ return (typeof record.relativePath === "string" &&
32
+ record.relativePath.startsWith("addons/godot_mcp/") &&
33
+ !record.relativePath.includes("\\") &&
34
+ !record.relativePath.split("/").includes("..") &&
35
+ record.relativePath.length <= 512 &&
36
+ typeof record.sha256 === "string" &&
37
+ /^[a-f0-9]{64}$/.test(record.sha256));
38
+ }
39
+ export function parseInstallManifest(value) {
40
+ if (typeof value !== "object" || value === null) {
41
+ throw new TypeError("Install manifest must be an object");
42
+ }
43
+ const manifest = value;
44
+ if (manifest.schemaVersion !== 1 ||
45
+ !supportedManifestVersion(manifest.productVersion) ||
46
+ typeof manifest.installedAt !== "string" ||
47
+ !Number.isFinite(Date.parse(manifest.installedAt)) ||
48
+ typeof manifest.manifestSha256 !== "string" ||
49
+ !/^[a-f0-9]{64}$/.test(manifest.manifestSha256) ||
50
+ !Array.isArray(manifest.files) ||
51
+ !manifest.files.every(isInstalledFile) ||
52
+ typeof manifest.projectFile !== "object" ||
53
+ manifest.projectFile === null ||
54
+ typeof manifest.projectFile.preimageBase64 !== "string" ||
55
+ typeof manifest.projectFile.preimageSha256 !== "string" ||
56
+ !/^[a-f0-9]{64}$/.test(manifest.projectFile.preimageSha256) ||
57
+ typeof manifest.projectFile.postimageSha256 !== "string" ||
58
+ !/^[a-f0-9]{64}$/.test(manifest.projectFile.postimageSha256) ||
59
+ typeof manifest.projectConfig !== "object" ||
60
+ manifest.projectConfig === null ||
61
+ typeof manifest.projectConfig.created !== "boolean" ||
62
+ typeof manifest.projectConfig.sha256 !== "string" ||
63
+ !/^[a-f0-9]{64}$/.test(manifest.projectConfig.sha256)) {
64
+ throw new TypeError("Install manifest has an invalid shape");
65
+ }
66
+ const files = [...manifest.files].sort((left, right) => left.relativePath.localeCompare(right.relativePath));
67
+ if (files.some((file, index) => file.relativePath !== manifest.files?.[index]?.relativePath)) {
68
+ throw new TypeError("Install manifest file entries are not sorted");
69
+ }
70
+ if (new Set(files.map((file) => file.relativePath)).size !== files.length)
71
+ throw new TypeError("Install manifest file entries are not unique");
72
+ if (hashFileEntries(files) !== manifest.manifestSha256) {
73
+ throw new TypeError("Install manifest digest does not match its file entries");
74
+ }
75
+ return manifest;
76
+ }
77
+ export async function readInstallManifest(projectRoot) {
78
+ return parseInstallManifest(JSON.parse(await readFile(manifestPath(projectRoot), "utf8")));
79
+ }
80
+ export async function writeInstallManifest(projectRoot, manifest) {
81
+ const path = manifestPath(projectRoot);
82
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
83
+ const temporary = `${path}.tmp-${process.pid}`;
84
+ await writeFile(temporary, `${JSON.stringify(manifest, null, 2)}\n`, { mode: 0o600 });
85
+ await rename(temporary, path);
86
+ }
87
+ export async function updateProjectPostimage(projectRoot) {
88
+ const manifest = await readInstallManifest(projectRoot);
89
+ const projectContents = await readFile(join(projectRoot, "project.godot"));
90
+ await writeInstallManifest(projectRoot, {
91
+ ...manifest,
92
+ projectFile: { ...manifest.projectFile, postimageSha256: sha256(projectContents) },
93
+ });
94
+ }
95
+ //# sourceMappingURL=addonManifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addonManifest.js","sourceRoot":"","sources":["../../src/install/addonManifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface DoctorCheck {
2
+ name: "project-config" | "addon-manifest" | "addon-files" | "plugin-enabled" | "godot-version" | "runtime-state";
3
+ status: "ok" | "warning" | "error";
4
+ detail: string;
5
+ }
6
+ export interface DoctorReport {
7
+ healthy: boolean;
8
+ checks: DoctorCheck[];
9
+ }
10
+ export declare function runDoctor(projectInput: string, godotBin?: string): Promise<DoctorReport>;
11
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/install/doctor.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,aAAa,GAAG,gBAAgB,GAAG,eAAe,GAAG,eAAe,CAAC;IACjH,MAAM,EAAE,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,wBAAsB,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA6E9F"}
@@ -0,0 +1,86 @@
1
+ import { readFile, readdir } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { discoverProject, ProjectConfigSchema } from "@godot-mcp/control-plane";
4
+ import { readInstallManifest, sha256 } from "./addonManifest.js";
5
+ import { godotVersion } from "./pluginState.js";
6
+ export async function runDoctor(projectInput, godotBin) {
7
+ const checks = [];
8
+ let root;
9
+ try {
10
+ root = (await discoverProject(projectInput)).rootRealPath;
11
+ }
12
+ catch (error) {
13
+ return {
14
+ healthy: false,
15
+ checks: [{ name: "project-config", status: "error", detail: error.message }],
16
+ };
17
+ }
18
+ try {
19
+ ProjectConfigSchema.parse(JSON.parse(await readFile(join(root, ".godot-mcp.json"), "utf8")));
20
+ checks.push({ name: "project-config", status: "ok", detail: "Project configuration is valid" });
21
+ }
22
+ catch {
23
+ checks.push({ name: "project-config", status: "error", detail: "Project configuration is missing or invalid" });
24
+ }
25
+ let manifest;
26
+ try {
27
+ manifest = await readInstallManifest(root);
28
+ checks.push({ name: "addon-manifest", status: "ok", detail: "Install manifest is valid" });
29
+ }
30
+ catch {
31
+ checks.push({ name: "addon-manifest", status: "error", detail: "Install manifest is missing or invalid" });
32
+ }
33
+ if (manifest) {
34
+ try {
35
+ for (const file of manifest.files) {
36
+ if (sha256(await readFile(join(root, file.relativePath))) !== file.sha256) {
37
+ throw new Error(file.relativePath);
38
+ }
39
+ }
40
+ checks.push({ name: "addon-files", status: "ok", detail: "Installed addon hashes match" });
41
+ }
42
+ catch (error) {
43
+ checks.push({ name: "addon-files", status: "error", detail: `Installed addon hash mismatch: ${error.message}` });
44
+ }
45
+ }
46
+ else {
47
+ checks.push({ name: "addon-files", status: "error", detail: "Cannot verify files without a valid manifest" });
48
+ }
49
+ try {
50
+ const projectFile = await readFile(join(root, "project.godot"), "utf8");
51
+ const enabled = projectFile.includes('"res://addons/godot_mcp/plugin.cfg"');
52
+ checks.push({
53
+ name: "plugin-enabled",
54
+ status: enabled ? "ok" : "error",
55
+ detail: enabled ? "Godot MCP editor plugin is enabled" : "Godot MCP editor plugin is disabled",
56
+ });
57
+ }
58
+ catch {
59
+ checks.push({ name: "plugin-enabled", status: "error", detail: "Could not inspect project.godot" });
60
+ }
61
+ try {
62
+ const version = await godotVersion(godotBin);
63
+ checks.push({ name: "godot-version", status: "ok", detail: version });
64
+ }
65
+ catch (error) {
66
+ checks.push({ name: "godot-version", status: "error", detail: error.message });
67
+ }
68
+ try {
69
+ const entries = await readdir(join(root, ".godot/godot-mcp/runtime"));
70
+ checks.push({
71
+ name: "runtime-state",
72
+ status: entries.length === 0 ? "ok" : "warning",
73
+ detail: entries.length === 0 ? "No stale runtime entries" : `${entries.length} runtime entries present`,
74
+ });
75
+ }
76
+ catch (error) {
77
+ if (error.code === "ENOENT") {
78
+ checks.push({ name: "runtime-state", status: "ok", detail: "No runtime directory" });
79
+ }
80
+ else {
81
+ checks.push({ name: "runtime-state", status: "error", detail: "Could not inspect runtime state" });
82
+ }
83
+ }
84
+ return { healthy: checks.every((check) => check.status !== "error"), checks };
85
+ }
86
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/install/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export type PluginStateAction = "enable" | "disable";
2
+ interface ProcessResult {
3
+ exitCode: number;
4
+ stdout: string;
5
+ stderr: string;
6
+ }
7
+ export declare function findGodotBinary(explicit?: string): Promise<string>;
8
+ export declare function runProcess(command: string, args: readonly string[], timeoutMs?: number): Promise<ProcessResult>;
9
+ export declare function godotVersion(godotBin?: string): Promise<string>;
10
+ export declare function setPluginState(projectInput: string, action: PluginStateAction, godotBin?: string): Promise<void>;
11
+ export {};
12
+ //# sourceMappingURL=pluginState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pluginState.d.ts","sourceRoot":"","sources":["../../src/install/pluginState.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,SAAS,CAAC;AAErD,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAWD,wBAAsB,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAYxE;AAED,wBAAgB,UAAU,CACxB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,SAAS,SAAS,GACjB,OAAO,CAAC,aAAa,CAAC,CAiCxB;AAED,wBAAsB,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQrE;AAED,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,iBAAiB,EACzB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAkBf"}
@@ -0,0 +1,95 @@
1
+ import { constants } from "node:fs";
2
+ import { access } from "node:fs/promises";
3
+ import { delimiter, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { spawn } from "node:child_process";
6
+ import { discoverProject } from "@godot-mcp/control-plane";
7
+ import { updateProjectPostimage } from "./addonManifest.js";
8
+ async function executable(path) {
9
+ try {
10
+ await access(path, constants.X_OK);
11
+ return true;
12
+ }
13
+ catch {
14
+ return false;
15
+ }
16
+ }
17
+ export async function findGodotBinary(explicit) {
18
+ const candidates = [
19
+ explicit,
20
+ process.env.GODOT_BIN,
21
+ "/opt/homebrew/bin/godot",
22
+ "/usr/local/bin/godot",
23
+ ...((process.env.PATH ?? "").split(delimiter).map((entry) => join(entry, "godot"))),
24
+ ].filter((candidate) => Boolean(candidate));
25
+ for (const candidate of [...new Set(candidates)]) {
26
+ if (await executable(candidate))
27
+ return candidate;
28
+ }
29
+ throw new Error("Godot executable not found; set GODOT_BIN to a Godot 4.7 binary");
30
+ }
31
+ export function runProcess(command, args, timeoutMs = 30_000) {
32
+ return new Promise((resolvePromise, reject) => {
33
+ const child = spawn(command, [...args], { stdio: ["ignore", "pipe", "pipe"] });
34
+ let stdout = "";
35
+ let stderr = "";
36
+ let timedOut = false;
37
+ child.stdout.setEncoding("utf8");
38
+ child.stderr.setEncoding("utf8");
39
+ child.stdout.on("data", (chunk) => {
40
+ stdout += chunk;
41
+ });
42
+ child.stderr.on("data", (chunk) => {
43
+ stderr += chunk;
44
+ });
45
+ const timeout = setTimeout(() => {
46
+ timedOut = true;
47
+ child.kill("SIGKILL");
48
+ }, timeoutMs);
49
+ child.once("error", (error) => {
50
+ clearTimeout(timeout);
51
+ reject(error);
52
+ });
53
+ child.once("close", (code) => {
54
+ clearTimeout(timeout);
55
+ if (timedOut) {
56
+ reject(new Error(`Process timed out after ${timeoutMs}ms`));
57
+ }
58
+ else if (code === null) {
59
+ reject(new Error("Process exited without a status code"));
60
+ }
61
+ else {
62
+ resolvePromise({ exitCode: code, stdout, stderr });
63
+ }
64
+ });
65
+ });
66
+ }
67
+ export async function godotVersion(godotBin) {
68
+ const binary = await findGodotBinary(godotBin);
69
+ const result = await runProcess(binary, ["--version"], 5_000);
70
+ const version = result.stdout.trim();
71
+ if (result.exitCode !== 0 || !version.startsWith("4.7.stable")) {
72
+ throw new Error(`Godot 4.7.stable is required; detected ${version || "unknown"}`);
73
+ }
74
+ return version;
75
+ }
76
+ export async function setPluginState(projectInput, action, godotBin) {
77
+ const project = await discoverProject(projectInput);
78
+ const binary = await findGodotBinary(godotBin);
79
+ await godotVersion(binary);
80
+ const helper = fileURLToPath(new URL("../../godot/plugin_state.gd", import.meta.url));
81
+ const result = await runProcess(binary, [
82
+ "--headless",
83
+ "--path",
84
+ project.rootRealPath,
85
+ "--script",
86
+ helper,
87
+ "--",
88
+ action,
89
+ ]);
90
+ if (result.exitCode !== 0) {
91
+ throw new Error(`Godot failed to ${action} the addon: ${result.stderr || result.stdout}`);
92
+ }
93
+ await updateProjectPostimage(project.rootRealPath);
94
+ }
95
+ //# sourceMappingURL=pluginState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pluginState.js","sourceRoot":"","sources":["../../src/install/pluginState.ts"],"names":[],"mappings":"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"}