@godot-mcp/control-plane 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 (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -2
  3. package/dist/audit/jsonlAuditSink.d.ts +33 -0
  4. package/dist/audit/jsonlAuditSink.d.ts.map +1 -0
  5. package/dist/audit/jsonlAuditSink.js +57 -0
  6. package/dist/audit/jsonlAuditSink.js.map +1 -0
  7. package/dist/audit/redact.d.ts +2 -0
  8. package/dist/audit/redact.d.ts.map +1 -0
  9. package/dist/audit/redact.js +44 -0
  10. package/dist/audit/redact.js.map +1 -0
  11. package/dist/auth/pairingDescriptor.d.ts +44 -0
  12. package/dist/auth/pairingDescriptor.d.ts.map +1 -0
  13. package/dist/auth/pairingDescriptor.js +91 -0
  14. package/dist/auth/pairingDescriptor.js.map +1 -0
  15. package/dist/auth/runtimeDirectory.d.ts +3 -0
  16. package/dist/auth/runtimeDirectory.d.ts.map +1 -0
  17. package/dist/auth/runtimeDirectory.js +30 -0
  18. package/dist/auth/runtimeDirectory.js.map +1 -0
  19. package/dist/auth/sessionCrypto.d.ts +18 -0
  20. package/dist/auth/sessionCrypto.d.ts.map +1 -0
  21. package/dist/auth/sessionCrypto.js +118 -0
  22. package/dist/auth/sessionCrypto.js.map +1 -0
  23. package/dist/editor/editorMutationService.d.ts +21 -0
  24. package/dist/editor/editorMutationService.d.ts.map +1 -0
  25. package/dist/editor/editorMutationService.js +120 -0
  26. package/dist/editor/editorMutationService.js.map +1 -0
  27. package/dist/editor/mutationLedger.d.ts +30 -0
  28. package/dist/editor/mutationLedger.d.ts.map +1 -0
  29. package/dist/editor/mutationLedger.js +133 -0
  30. package/dist/editor/mutationLedger.js.map +1 -0
  31. package/dist/errors.d.ts +12 -0
  32. package/dist/errors.d.ts.map +1 -0
  33. package/dist/errors.js +23 -0
  34. package/dist/errors.js.map +1 -0
  35. package/dist/evidence/evidenceStore.d.ts +63 -0
  36. package/dist/evidence/evidenceStore.d.ts.map +1 -0
  37. package/dist/evidence/evidenceStore.js +350 -0
  38. package/dist/evidence/evidenceStore.js.map +1 -0
  39. package/dist/extensions/extensionRegistry.d.ts +33 -0
  40. package/dist/extensions/extensionRegistry.d.ts.map +1 -0
  41. package/dist/extensions/extensionRegistry.js +37 -0
  42. package/dist/extensions/extensionRegistry.js.map +1 -0
  43. package/dist/help/coreHelp.d.ts +10 -0
  44. package/dist/help/coreHelp.d.ts.map +1 -0
  45. package/dist/help/coreHelp.js +82 -0
  46. package/dist/help/coreHelp.js.map +1 -0
  47. package/dist/index.d.ts +37 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +37 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/policy/authorize.d.ts +5 -0
  52. package/dist/policy/authorize.d.ts.map +1 -0
  53. package/dist/policy/authorize.js +19 -0
  54. package/dist/policy/authorize.js.map +1 -0
  55. package/dist/policy/capabilities.d.ts +36 -0
  56. package/dist/policy/capabilities.d.ts.map +1 -0
  57. package/dist/policy/capabilities.js +129 -0
  58. package/dist/policy/capabilities.js.map +1 -0
  59. package/dist/project/artifactStore.d.ts +32 -0
  60. package/dist/project/artifactStore.d.ts.map +1 -0
  61. package/dist/project/artifactStore.js +172 -0
  62. package/dist/project/artifactStore.js.map +1 -0
  63. package/dist/project/pathPolicy.d.ts +4 -0
  64. package/dist/project/pathPolicy.d.ts.map +1 -0
  65. package/dist/project/pathPolicy.js +74 -0
  66. package/dist/project/pathPolicy.js.map +1 -0
  67. package/dist/project/projectConfig.d.ts +10 -0
  68. package/dist/project/projectConfig.d.ts.map +1 -0
  69. package/dist/project/projectConfig.js +63 -0
  70. package/dist/project/projectConfig.js.map +1 -0
  71. package/dist/project/projectIdentity.d.ts +8 -0
  72. package/dist/project/projectIdentity.d.ts.map +1 -0
  73. package/dist/project/projectIdentity.js +58 -0
  74. package/dist/project/projectIdentity.js.map +1 -0
  75. package/dist/project/projectJobJournal.d.ts +49 -0
  76. package/dist/project/projectJobJournal.d.ts.map +1 -0
  77. package/dist/project/projectJobJournal.js +67 -0
  78. package/dist/project/projectJobJournal.js.map +1 -0
  79. package/dist/project/projectJobService.d.ts +52 -0
  80. package/dist/project/projectJobService.d.ts.map +1 -0
  81. package/dist/project/projectJobService.js +289 -0
  82. package/dist/project/projectJobService.js.map +1 -0
  83. package/dist/project/projectMutationService.d.ts +40 -0
  84. package/dist/project/projectMutationService.d.ts.map +1 -0
  85. package/dist/project/projectMutationService.js +145 -0
  86. package/dist/project/projectMutationService.js.map +1 -0
  87. package/dist/project/projectPreflight.d.ts +7 -0
  88. package/dist/project/projectPreflight.d.ts.map +1 -0
  89. package/dist/project/projectPreflight.js +50 -0
  90. package/dist/project/projectPreflight.js.map +1 -0
  91. package/dist/project/projectProcess.d.ts +40 -0
  92. package/dist/project/projectProcess.d.ts.map +1 -0
  93. package/dist/project/projectProcess.js +196 -0
  94. package/dist/project/projectProcess.js.map +1 -0
  95. package/dist/project/projectService.d.ts +20 -0
  96. package/dist/project/projectService.d.ts.map +1 -0
  97. package/dist/project/projectService.js +35 -0
  98. package/dist/project/projectService.js.map +1 -0
  99. package/dist/project/secureJournalFile.d.ts +3 -0
  100. package/dist/project/secureJournalFile.d.ts.map +1 -0
  101. package/dist/project/secureJournalFile.js +56 -0
  102. package/dist/project/secureJournalFile.js.map +1 -0
  103. package/dist/runtime/debugTokenStore.d.ts +41 -0
  104. package/dist/runtime/debugTokenStore.d.ts.map +1 -0
  105. package/dist/runtime/debugTokenStore.js +105 -0
  106. package/dist/runtime/debugTokenStore.js.map +1 -0
  107. package/dist/runtime/debuggerClient.d.ts +14 -0
  108. package/dist/runtime/debuggerClient.d.ts.map +1 -0
  109. package/dist/runtime/debuggerClient.js +21 -0
  110. package/dist/runtime/debuggerClient.js.map +1 -0
  111. package/dist/runtime/inputReceipt.d.ts +15 -0
  112. package/dist/runtime/inputReceipt.d.ts.map +1 -0
  113. package/dist/runtime/inputReceipt.js +36 -0
  114. package/dist/runtime/inputReceipt.js.map +1 -0
  115. package/dist/runtime/runtimeDescriptor.d.ts +50 -0
  116. package/dist/runtime/runtimeDescriptor.d.ts.map +1 -0
  117. package/dist/runtime/runtimeDescriptor.js +175 -0
  118. package/dist/runtime/runtimeDescriptor.js.map +1 -0
  119. package/dist/runtime/runtimeProcess.d.ts +39 -0
  120. package/dist/runtime/runtimeProcess.d.ts.map +1 -0
  121. package/dist/runtime/runtimeProcess.js +180 -0
  122. package/dist/runtime/runtimeProcess.js.map +1 -0
  123. package/dist/runtime/runtimeService.d.ts +130 -0
  124. package/dist/runtime/runtimeService.d.ts.map +1 -0
  125. package/dist/runtime/runtimeService.js +919 -0
  126. package/dist/runtime/runtimeService.js.map +1 -0
  127. package/dist/session/sessionService.d.ts +52 -0
  128. package/dist/session/sessionService.d.ts.map +1 -0
  129. package/dist/session/sessionService.js +72 -0
  130. package/dist/session/sessionService.js.map +1 -0
  131. package/dist/unsafe/unsafeFixtureAuthority.d.ts +27 -0
  132. package/dist/unsafe/unsafeFixtureAuthority.d.ts.map +1 -0
  133. package/dist/unsafe/unsafeFixtureAuthority.js +130 -0
  134. package/dist/unsafe/unsafeFixtureAuthority.js.map +1 -0
  135. package/dist/unsafe/unsafeFixtureProcess.d.ts +30 -0
  136. package/dist/unsafe/unsafeFixtureProcess.d.ts.map +1 -0
  137. package/dist/unsafe/unsafeFixtureProcess.js +119 -0
  138. package/dist/unsafe/unsafeFixtureProcess.js.map +1 -0
  139. package/dist/unsafe/unsafeFixtureService.d.ts +41 -0
  140. package/dist/unsafe/unsafeFixtureService.d.ts.map +1 -0
  141. package/dist/unsafe/unsafeFixtureService.js +162 -0
  142. package/dist/unsafe/unsafeFixtureService.js.map +1 -0
  143. package/dist/visual/pngComparison.d.ts +12 -0
  144. package/dist/visual/pngComparison.d.ts.map +1 -0
  145. package/dist/visual/pngComparison.js +136 -0
  146. package/dist/visual/pngComparison.js.map +1 -0
  147. package/dist/visual/scenarioService.d.ts +50 -0
  148. package/dist/visual/scenarioService.d.ts.map +1 -0
  149. package/dist/visual/scenarioService.js +421 -0
  150. package/dist/visual/scenarioService.js.map +1 -0
  151. package/dist/visual/visualService.d.ts +27 -0
  152. package/dist/visual/visualService.d.ts.map +1 -0
  153. package/dist/visual/visualService.js +70 -0
  154. package/dist/visual/visualService.js.map +1 -0
  155. package/package.json +26 -6
  156. package/index.js +0 -1
@@ -0,0 +1,40 @@
1
+ import { type ProjectMutationResult, type ProjectOperationInput } from "@godot-mcp/protocol";
2
+ type ProjectMutationInput = Extract<ProjectOperationInput, {
3
+ operation: "settings_apply" | "plugin_set";
4
+ }>;
5
+ export declare class ProjectMutationJournal {
6
+ private readonly path;
7
+ private readonly latest;
8
+ private tail;
9
+ static open(path: string): Promise<ProjectMutationJournal>;
10
+ private constructor();
11
+ reconcile(key: string, requestDigest: string): {
12
+ state: "missing" | "unknown";
13
+ } | {
14
+ state: "completed";
15
+ result: ProjectMutationResult;
16
+ };
17
+ begin(key: string, requestDigest: string): Promise<void>;
18
+ complete(key: string, requestDigest: string, result: ProjectMutationResult): Promise<void>;
19
+ private append;
20
+ private remember;
21
+ }
22
+ export interface ProjectMutationBridge {
23
+ request(method: "project.operation", params: unknown, options: {
24
+ timeoutMs: number;
25
+ maxResponseBytes: number;
26
+ correlationId: string;
27
+ }): Promise<{
28
+ data: unknown;
29
+ }>;
30
+ }
31
+ export declare class ProjectMutationService {
32
+ private readonly bridge;
33
+ private readonly journal;
34
+ private tail;
35
+ constructor(bridge: () => ProjectMutationBridge | null, journal: ProjectMutationJournal);
36
+ execute(rawInput: ProjectMutationInput, correlationId: string): Promise<ProjectMutationResult>;
37
+ private executeExclusive;
38
+ }
39
+ export {};
40
+ //# sourceMappingURL=projectMutationService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectMutationService.d.ts","sourceRoot":"","sources":["../../src/project/projectMutationService.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC3B,MAAM,qBAAqB,CAAC;AAM7B,KAAK,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,EAAE;IAAE,SAAS,EAAE,gBAAgB,GAAG,YAAY,CAAA;CAAE,CAAC,CAAC;AAgC3G,qBAAa,sBAAsB;IAuBb,OAAO,CAAC,QAAQ,CAAC,IAAI;IAtBzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;IAC3D,OAAO,CAAC,IAAI,CAAuC;WAEtC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAmBhE,OAAO;IAEP,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,SAAS,GAAG,SAAS,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,qBAAqB,CAAA;KAAE;IAOjI,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;YAIlF,MAAM;IASpB,OAAO,CAAC,QAAQ;CAKjB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,MAAM,EAAE,mBAAmB,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACpK;AAED,qBAAa,sBAAsB;IAGrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAsC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFjG,OAAO,CAAC,IAAI,CAAoC;gBAEnB,MAAM,EAAE,MAAM,qBAAqB,GAAG,IAAI,EAAmB,OAAO,EAAE,sBAAsB;IAEnH,OAAO,CAAC,QAAQ,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;YAMtF,gBAAgB;CAqB/B"}
@@ -0,0 +1,145 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { ProjectMutationResultSchema, ProjectOperationInputSchema, canonicalFloat64Le, canonicalJson, } from "@godot-mcp/protocol";
3
+ import { z } from "zod";
4
+ import { GodotMcpException } from "../errors.js";
5
+ import { appendSecureJournal, readSecureJournal } from "./secureJournalFile.js";
6
+ const Sha256Schema = z.string().regex(/^[a-f0-9]{64}$/);
7
+ const MAX_JOURNAL_BYTES = 4 * 1024 * 1024;
8
+ const RecordSchema = z.discriminatedUnion("state", [
9
+ z.object({ schemaVersion: z.literal(1), state: z.literal("started"), keySha256: Sha256Schema, requestDigest: Sha256Schema, recordedAt: z.string().datetime() }).strict(),
10
+ z.object({ schemaVersion: z.literal(1), state: z.literal("completed"), keySha256: Sha256Schema, requestDigest: Sha256Schema, recordedAt: z.string().datetime(), result: ProjectMutationResultSchema }).strict(),
11
+ ]);
12
+ function sha256(value) {
13
+ return createHash("sha256").update(value).digest("hex");
14
+ }
15
+ function settingValueSha256(value) {
16
+ const canonical = typeof value === "number" && !Number.isSafeInteger(value)
17
+ ? canonicalJson({ $godotMcpFloat64Le: canonicalFloat64Le(value) })
18
+ : canonicalJson(value);
19
+ return sha256(canonical);
20
+ }
21
+ function conflict(message, partialEffects = false) {
22
+ return new GodotMcpException({
23
+ code: "CONFLICT",
24
+ message,
25
+ retryable: false,
26
+ correlationId: randomUUID(),
27
+ partialEffects,
28
+ rollback: partialEffects ? "not_attempted" : "not_needed",
29
+ });
30
+ }
31
+ export class ProjectMutationJournal {
32
+ path;
33
+ latest = new Map();
34
+ tail = Promise.resolve();
35
+ static async open(path) {
36
+ const journal = new ProjectMutationJournal(path);
37
+ try {
38
+ const text = await readSecureJournal(path, MAX_JOURNAL_BYTES);
39
+ if (text === null)
40
+ return journal;
41
+ for (const [index, line] of text.split("\n").entries()) {
42
+ if (!line)
43
+ continue;
44
+ try {
45
+ journal.remember(RecordSchema.parse(JSON.parse(line)));
46
+ }
47
+ catch {
48
+ throw conflict(`Project mutation journal record ${index + 1} is malformed`);
49
+ }
50
+ }
51
+ }
52
+ catch (error) {
53
+ if (error.code !== "ENOENT")
54
+ throw error;
55
+ }
56
+ return journal;
57
+ }
58
+ constructor(path) {
59
+ this.path = path;
60
+ }
61
+ reconcile(key, requestDigest) {
62
+ const record = this.latest.get(sha256(key));
63
+ if (!record)
64
+ return { state: "missing" };
65
+ if (record.requestDigest !== requestDigest)
66
+ throw conflict("Idempotency key was already used for another project mutation");
67
+ return record.state === "completed" ? { state: "completed", result: record.result } : { state: "unknown" };
68
+ }
69
+ async begin(key, requestDigest) {
70
+ await this.append({ schemaVersion: 1, state: "started", keySha256: sha256(key), requestDigest, recordedAt: new Date().toISOString() });
71
+ }
72
+ async complete(key, requestDigest, result) {
73
+ await this.append({ schemaVersion: 1, state: "completed", keySha256: sha256(key), requestDigest, recordedAt: new Date().toISOString(), result });
74
+ }
75
+ async append(record) {
76
+ const write = this.tail.then(async () => {
77
+ await appendSecureJournal(this.path, `${JSON.stringify(record)}\n`);
78
+ this.remember(record);
79
+ });
80
+ this.tail = write.catch(() => undefined);
81
+ await write;
82
+ }
83
+ remember(record) {
84
+ this.latest.delete(record.keySha256);
85
+ this.latest.set(record.keySha256, record);
86
+ while (this.latest.size > 256)
87
+ this.latest.delete(this.latest.keys().next().value);
88
+ }
89
+ }
90
+ export class ProjectMutationService {
91
+ bridge;
92
+ journal;
93
+ tail = Promise.resolve();
94
+ constructor(bridge, journal) {
95
+ this.bridge = bridge;
96
+ this.journal = journal;
97
+ }
98
+ async execute(rawInput, correlationId) {
99
+ const run = this.tail.then(() => this.executeExclusive(rawInput, correlationId));
100
+ this.tail = run.then(() => undefined, () => undefined);
101
+ return run;
102
+ }
103
+ async executeExclusive(rawInput, correlationId) {
104
+ const parsed = ProjectOperationInputSchema.parse(rawInput);
105
+ if (parsed.operation !== "settings_apply" && parsed.operation !== "plugin_set")
106
+ throw conflict("Operation is not a project mutation");
107
+ const input = parsed;
108
+ const requestDigest = sha256(JSON.stringify(input));
109
+ const reconciliation = this.journal.reconcile(input.idempotencyKey, requestDigest);
110
+ if (reconciliation.state === "completed")
111
+ return reconciliation.result;
112
+ if (reconciliation.state === "unknown")
113
+ throw conflict("A prior project mutation has an unknown outcome; reconcile project state before using a new key", true);
114
+ const bridge = this.bridge();
115
+ if (!bridge) {
116
+ throw new GodotMcpException({ code: "NOT_ATTACHED", message: "Godot editor addon is not attached", retryable: true, correlationId, partialEffects: false, rollback: "not_needed" });
117
+ }
118
+ await this.journal.begin(input.idempotencyKey, requestDigest);
119
+ const response = await bridge.request("project.operation", input, { timeoutMs: 30_000, maxResponseBytes: 256 * 1024, correlationId });
120
+ const result = ProjectMutationResultSchema.parse(response.data);
121
+ if (!receiptMatchesRequest(input, result)) {
122
+ throw conflict("Godot returned a mismatched project mutation receipt", true);
123
+ }
124
+ await this.journal.complete(input.idempotencyKey, requestDigest, result);
125
+ return result;
126
+ }
127
+ }
128
+ function receiptMatchesRequest(input, result) {
129
+ if (result.operation !== input.operation)
130
+ return false;
131
+ if (result.operation === "plugin_set" && input.operation === "plugin_set") {
132
+ return result.pluginSha256 === sha256(input.pluginPath) && result.enabled === input.enabled;
133
+ }
134
+ if (result.operation !== "settings_apply" || input.operation !== "settings_apply" || result.changes.length !== input.changes.length)
135
+ return false;
136
+ return result.changes.every((receipt, index) => {
137
+ const change = input.changes[index];
138
+ if (!change)
139
+ return false;
140
+ if (receipt.settingNameSha256 !== sha256(change.name) || receipt.postimageSha256 !== settingValueSha256(change.value))
141
+ return false;
142
+ return change.expectedValue === undefined || receipt.preimageSha256 === settingValueSha256(change.expectedValue);
143
+ });
144
+ }
145
+ //# sourceMappingURL=projectMutationService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectMutationService.js","sourceRoot":"","sources":["../../src/project/projectMutationService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,kBAAkB,EAClB,aAAa,GAGd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGhF,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;AACxD,MAAM,iBAAiB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAE1C,MAAM,YAAY,GAAG,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE;IACjD,CAAC,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACxK,CAAC,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC,CAAC,MAAM,EAAE;CAChN,CAAC,CAAC;AAGH,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAuC;IACjE,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;QACzE,CAAC,CAAC,aAAa,CAAC,EAAE,kBAAkB,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QAClE,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACzB,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,QAAQ,CAAC,OAAe,EAAE,cAAc,GAAG,KAAK;IACvD,OAAO,IAAI,iBAAiB,CAAC;QAC3B,IAAI,EAAE,UAAU;QAChB,OAAO;QACP,SAAS,EAAE,KAAK;QAChB,aAAa,EAAE,UAAU,EAAE;QAC3B,cAAc;QACd,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,YAAY;KAC1D,CAAC,CAAC;AACL,CAAC;AAED,MAAM,OAAO,sBAAsB;IAuBI;IAtBpB,MAAM,GAAG,IAAI,GAAG,EAAyB,CAAC;IACnD,IAAI,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAC;IAEnD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAY;QAC5B,MAAM,OAAO,GAAG,IAAI,sBAAsB,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC9D,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAO,OAAO,CAAC;YAClC,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;gBACvD,IAAI,CAAC,IAAI;oBAAE,SAAS;gBACpB,IAAI,CAAC;oBACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC,CAAC,CAAC;gBACpE,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,QAAQ,CAAC,mCAAmC,KAAK,GAAG,CAAC,eAAe,CAAC,CAAC;gBAC9E,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,KAAK,CAAC;QACtE,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,YAAqC,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAErD,SAAS,CAAC,GAAW,EAAE,aAAqB;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QACzC,IAAI,MAAM,CAAC,aAAa,KAAK,aAAa;YAAE,MAAM,QAAQ,CAAC,+DAA+D,CAAC,CAAC;QAC5H,OAAO,MAAM,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC7G,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,GAAW,EAAE,aAAqB;QAC5C,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACzI,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,GAAW,EAAE,aAAqB,EAAE,MAA6B;QAC9E,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACnJ,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,MAAqB;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YACtC,MAAM,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACpE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,KAAK,CAAC;IACd,CAAC;IAEO,QAAQ,CAAC,MAAqB;QACpC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,GAAG;YAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAe,CAAC,CAAC;IAC/F,CAAC;CACF;AAMD,MAAM,OAAO,sBAAsB;IAGJ;IAA6D;IAFlF,IAAI,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAEhD,YAA6B,MAA0C,EAAmB,OAA+B;QAA5F,WAAM,GAAN,MAAM,CAAoC;QAAmB,YAAO,GAAP,OAAO,CAAwB;IAAG,CAAC;IAE7H,KAAK,CAAC,OAAO,CAAC,QAA8B,EAAE,aAAqB;QACjE,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC;QACjF,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACvD,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,QAA8B,EAAE,aAAqB;QAClF,MAAM,MAAM,GAAG,2BAA2B,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC3D,IAAI,MAAM,CAAC,SAAS,KAAK,gBAAgB,IAAI,MAAM,CAAC,SAAS,KAAK,YAAY;YAAE,MAAM,QAAQ,CAAC,qCAAqC,CAAC,CAAC;QACtI,MAAM,KAAK,GAAG,MAAM,CAAC;QACrB,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;QACnF,IAAI,cAAc,CAAC,KAAK,KAAK,WAAW;YAAE,OAAO,cAAc,CAAC,MAAM,CAAC;QACvE,IAAI,cAAc,CAAC,KAAK,KAAK,SAAS;YAAE,MAAM,QAAQ,CAAC,iGAAiG,EAAE,IAAI,CAAC,CAAC;QAChK,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,iBAAiB,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,oCAAoC,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;QACtL,CAAC;QACD,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,mBAAmB,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,GAAG,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;QACtI,MAAM,MAAM,GAAG,2BAA2B,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAChE,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;YAC1C,MAAM,QAAQ,CAAC,sDAAsD,EAAE,IAAI,CAAC,CAAC;QAC/E,CAAC;QACD,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;QACzE,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAED,SAAS,qBAAqB,CAAC,KAA2B,EAAE,MAA6B;IACvF,IAAI,MAAM,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IACvD,IAAI,MAAM,CAAC,SAAS,KAAK,YAAY,IAAI,KAAK,CAAC,SAAS,KAAK,YAAY,EAAE,CAAC;QAC1E,OAAO,MAAM,CAAC,YAAY,KAAK,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC;IAC9F,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,KAAK,gBAAgB,IAAI,KAAK,CAAC,SAAS,KAAK,gBAAgB,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAClJ,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QAC7C,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC1B,IAAI,OAAO,CAAC,iBAAiB,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,eAAe,KAAK,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACpI,OAAO,MAAM,CAAC,aAAa,KAAK,SAAS,IAAI,OAAO,CAAC,cAAc,KAAK,kBAAkB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACnH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare function assertBuildSolutionsPreflight(projectRoot: string): Promise<void>;
2
+ export declare function assertExportPreflight(projectRoot: string, presetName: string): Promise<void>;
3
+ export declare function projectOperationPreflight(projectRoot: string, input: {
4
+ operation: string;
5
+ preset?: string;
6
+ }): Promise<void>;
7
+ //# sourceMappingURL=projectPreflight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectPreflight.d.ts","sourceRoot":"","sources":["../../src/project/projectPreflight.ts"],"names":[],"mappings":"AAkBA,wBAAsB,6BAA6B,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKtF;AAED,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAelG;AAED,wBAAsB,yBAAyB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjI"}
@@ -0,0 +1,50 @@
1
+ import { lstat, readdir, readFile, realpath } from "node:fs/promises";
2
+ import { resolve, sep } from "node:path";
3
+ import { GodotMcpException } from "../errors.js";
4
+ function denied(message) {
5
+ return new GodotMcpException({ code: "CONFLICT", message, retryable: false, correlationId: "project-preflight", partialEffects: false, rollback: "not_needed" });
6
+ }
7
+ async function containedRegularFile(projectRoot, relativePath) {
8
+ const root = await realpath(projectRoot);
9
+ const path = resolve(root, relativePath);
10
+ if (!path.startsWith(`${root}${sep}`))
11
+ throw denied("Project preflight path escaped the project");
12
+ const metadata = await lstat(path);
13
+ if (metadata.isSymbolicLink() || !metadata.isFile())
14
+ throw denied("Project preflight input is not a regular file");
15
+ return path;
16
+ }
17
+ export async function assertBuildSolutionsPreflight(projectRoot) {
18
+ const entries = await readdir(projectRoot, { withFileTypes: true });
19
+ if (!entries.some((entry) => entry.isFile() && (entry.name.endsWith(".sln") || entry.name.endsWith(".csproj")))) {
20
+ throw denied("Build solutions requires a top-level .sln or .csproj file");
21
+ }
22
+ }
23
+ export async function assertExportPreflight(projectRoot, presetName) {
24
+ let text;
25
+ try {
26
+ text = await readFile(await containedRegularFile(projectRoot, "export_presets.cfg"), "utf8");
27
+ }
28
+ catch (error) {
29
+ if (error instanceof GodotMcpException)
30
+ throw error;
31
+ throw denied("Export requires export_presets.cfg");
32
+ }
33
+ if (Buffer.byteLength(text) > 1024 * 1024)
34
+ throw denied("Export preset file exceeds 1 MiB");
35
+ const sections = text.split(/^\[preset\.\d+\]\s*$/mu).slice(1);
36
+ const section = sections.find((candidate) => candidate.match(/^name="(.*)"$/mu)?.[1] === presetName);
37
+ if (!section)
38
+ throw denied("Selected export preset does not exist");
39
+ const excludes = section.match(/^exclude_filter="(.*)"$/mu)?.[1]?.split(",").map((value) => value.trim()) ?? [];
40
+ if (!excludes.includes("addons/godot_mcp/**")) {
41
+ throw denied("Export preset must exclude addons/godot_mcp/**");
42
+ }
43
+ }
44
+ export async function projectOperationPreflight(projectRoot, input) {
45
+ if (input.operation === "build_start")
46
+ await assertBuildSolutionsPreflight(projectRoot);
47
+ if (input.operation === "export_start")
48
+ await assertExportPreflight(projectRoot, input.preset ?? "");
49
+ }
50
+ //# sourceMappingURL=projectPreflight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectPreflight.js","sourceRoot":"","sources":["../../src/project/projectPreflight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,SAAS,MAAM,CAAC,OAAe;IAC7B,OAAO,IAAI,iBAAiB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;AACnK,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,WAAmB,EAAE,YAAoB;IAC3E,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACzC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,GAAG,EAAE,CAAC;QAAE,MAAM,MAAM,CAAC,4CAA4C,CAAC,CAAC;IAClG,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;QAAE,MAAM,MAAM,CAAC,+CAA+C,CAAC,CAAC;IACnH,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,WAAmB;IACrE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAChH,MAAM,MAAM,CAAC,2DAA2D,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,WAAmB,EAAE,UAAkB;IACjF,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QAAC,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,oBAAoB,CAAC,WAAW,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAC;IAAC,CAAC;IACrG,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,KAAK,YAAY,iBAAiB;YAAE,MAAM,KAAK,CAAC;QACpD,MAAM,MAAM,CAAC,oCAAoC,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;QAAE,MAAM,MAAM,CAAC,kCAAkC,CAAC,CAAC;IAC5F,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC;IACrG,IAAI,CAAC,OAAO;QAAE,MAAM,MAAM,CAAC,uCAAuC,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;IAChH,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC;QAC9C,MAAM,MAAM,CAAC,gDAAgD,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,WAAmB,EAAE,KAA6C;IAChH,IAAI,KAAK,CAAC,SAAS,KAAK,aAAa;QAAE,MAAM,6BAA6B,CAAC,WAAW,CAAC,CAAC;IACxF,IAAI,KAAK,CAAC,SAAS,KAAK,cAAc;QAAE,MAAM,qBAAqB,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;AACvG,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { type OwnedRuntimeProcess } from "../runtime/runtimeProcess.js";
2
+ export type ProjectProcessInput = {
3
+ operation: "import";
4
+ projectRoot: string;
5
+ } | {
6
+ operation: "run";
7
+ projectRoot: string;
8
+ headless: boolean;
9
+ scenePath?: string;
10
+ } | {
11
+ operation: "build";
12
+ projectRoot: string;
13
+ } | {
14
+ operation: "export";
15
+ projectRoot: string;
16
+ artifactRoot: string;
17
+ mode: "release" | "debug" | "pack";
18
+ preset: string;
19
+ outputPath: string;
20
+ };
21
+ export declare function projectGodotArguments(input: ProjectProcessInput): string[];
22
+ export declare function scrubProjectEnvironment(environment: NodeJS.ProcessEnv): Record<string, string>;
23
+ export declare function projectProcessFingerprint(pid: number): Promise<string>;
24
+ export declare class OwnedProjectProcess implements OwnedRuntimeProcess {
25
+ private readonly child;
26
+ readonly pid: number;
27
+ readonly fingerprint: string;
28
+ private stopPromise;
29
+ private output;
30
+ private constructor();
31
+ static launch(input: ProjectProcessInput & {
32
+ godotBin: string;
33
+ environment?: NodeJS.ProcessEnv;
34
+ }): Promise<OwnedProjectProcess>;
35
+ diagnostics(): string;
36
+ wait(): Promise<number>;
37
+ stop(graceMs?: number): Promise<void>;
38
+ }
39
+ export declare function recoverOwnedProjectProcess(pid: number, fingerprint: string): Promise<"stopped" | "missing" | "ambiguous">;
40
+ //# sourceMappingURL=projectProcess.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectProcess.d.ts","sourceRoot":"","sources":["../../src/project/projectProcess.ts"],"names":[],"mappings":"AAKA,OAAO,EAA6C,KAAK,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AASnH,MAAM,MAAM,mBAAmB,GAC3B;IAAE,SAAS,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,SAAS,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAChF;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,SAAS,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAM/I,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,EAAE,CAwB1E;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAK9F;AAED,wBAAsB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK5E;AAUD,qBAAa,mBAAoB,YAAW,mBAAmB;IAK3D,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM;IAN9B,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,MAAM,CAAM;IAEpB,OAAO;WAMM,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA6BrI,WAAW,IAAI,MAAM;IAIrB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAIvB,IAAI,CAAC,OAAO,SAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAoCrC;AAED,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC,CAsB/H"}
@@ -0,0 +1,196 @@
1
+ import { execFile, spawn } from "node:child_process";
2
+ import { isAbsolute, resolve, sep } from "node:path";
3
+ import { promisify } from "node:util";
4
+ import { GodotMcpException } from "../errors.js";
5
+ import { childHasExited, shouldRefuseProcessSignal } from "../runtime/runtimeProcess.js";
6
+ const execFileAsync = promisify(execFile);
7
+ const ENVIRONMENT_ALLOWLIST = [
8
+ "HOME", "LANG", "LC_ALL", "LC_CTYPE", "PATH", "TMPDIR", "XDG_RUNTIME_DIR",
9
+ "DOTNET_ROOT", "JAVA_HOME", "ANDROID_HOME", "ANDROID_SDK_ROOT",
10
+ ];
11
+ const PRESET_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_. -]{0,63}$/;
12
+ function validateProjectRoot(projectRoot) {
13
+ if (!isAbsolute(projectRoot) || projectRoot.includes("\0"))
14
+ throw new TypeError("Project root must be an absolute path");
15
+ }
16
+ export function projectGodotArguments(input) {
17
+ validateProjectRoot(input.projectRoot);
18
+ if (input.operation === "import")
19
+ return ["--headless", "--editor", "--path", input.projectRoot, "--import"];
20
+ if (input.operation === "run") {
21
+ if (input.scenePath !== undefined && (!input.scenePath.startsWith("res://") ||
22
+ !input.scenePath.endsWith(".tscn") ||
23
+ input.scenePath.length > 512 ||
24
+ input.scenePath.includes("\0") ||
25
+ input.scenePath.slice(6).split("/").includes("..")))
26
+ throw new TypeError("Project run scene is invalid");
27
+ return [
28
+ ...(input.headless ? ["--headless"] : []),
29
+ "--path", input.projectRoot,
30
+ ...(input.scenePath ? ["--scene", input.scenePath] : []),
31
+ ];
32
+ }
33
+ if (input.operation === "build")
34
+ return ["--headless", "--path", input.projectRoot, "--build-solutions", "--quit"];
35
+ if (!PRESET_PATTERN.test(input.preset))
36
+ throw new TypeError("Export preset name is invalid");
37
+ const artifactRoot = resolve(input.artifactRoot);
38
+ const outputPath = resolve(input.outputPath);
39
+ if (outputPath === artifactRoot || !outputPath.startsWith(`${artifactRoot}${sep}`))
40
+ throw new TypeError("Export output must stay inside the owned artifact root");
41
+ const flag = input.mode === "release" ? "--export-release" : input.mode === "debug" ? "--export-debug" : "--export-pack";
42
+ return ["--headless", "--path", input.projectRoot, flag, input.preset, outputPath];
43
+ }
44
+ export function scrubProjectEnvironment(environment) {
45
+ return Object.fromEntries(ENVIRONMENT_ALLOWLIST.flatMap((name) => {
46
+ const value = environment[name];
47
+ return value === undefined ? [] : [[name, value]];
48
+ }));
49
+ }
50
+ export async function projectProcessFingerprint(pid) {
51
+ const { stdout } = await execFileAsync("ps", ["-o", "lstart=", "-p", String(pid)]);
52
+ const started = stdout.trim();
53
+ if (!started)
54
+ throw new Error("Owned project process start time is unavailable");
55
+ return `${pid}:${started}`;
56
+ }
57
+ function waitForExit(child) {
58
+ if (childHasExited(child))
59
+ return Promise.resolve(child.exitCode ?? 1);
60
+ return new Promise((resolveWait, reject) => {
61
+ child.once("error", reject);
62
+ child.once("close", (code) => resolveWait(code ?? 1));
63
+ });
64
+ }
65
+ export class OwnedProjectProcess {
66
+ child;
67
+ pid;
68
+ fingerprint;
69
+ stopPromise;
70
+ output = "";
71
+ constructor(child, pid, fingerprint) {
72
+ this.child = child;
73
+ this.pid = pid;
74
+ this.fingerprint = fingerprint;
75
+ }
76
+ static async launch(input) {
77
+ const child = spawn(input.godotBin, projectGodotArguments(input), {
78
+ env: scrubProjectEnvironment(input.environment ?? process.env),
79
+ stdio: ["ignore", "pipe", "pipe"],
80
+ });
81
+ await new Promise((resolveSpawn, reject) => {
82
+ child.once("spawn", resolveSpawn);
83
+ child.once("error", reject);
84
+ });
85
+ const pid = child.pid;
86
+ if (!pid)
87
+ throw new Error("Godot project operation did not report a PID");
88
+ let fingerprint;
89
+ try {
90
+ fingerprint = await projectProcessFingerprint(pid);
91
+ }
92
+ catch (error) {
93
+ if (!childHasExited(child))
94
+ child.kill("SIGKILL");
95
+ await waitForExit(child).catch(() => undefined);
96
+ throw error;
97
+ }
98
+ const owned = new OwnedProjectProcess(child, pid, fingerprint);
99
+ const append = (chunk) => {
100
+ owned.output = `${owned.output}${chunk.toString()}`.slice(-4 * 1024 * 1024);
101
+ };
102
+ child.stdout?.on("data", append);
103
+ child.stderr?.on("data", append);
104
+ child.once("exit", (code, signal) => append(`\n[godot project operation exited: ${signal ?? `code ${code ?? "unknown"}`}]\n`));
105
+ return owned;
106
+ }
107
+ diagnostics() {
108
+ return this.output;
109
+ }
110
+ wait() {
111
+ return waitForExit(this.child);
112
+ }
113
+ stop(graceMs = 2_000) {
114
+ if (!this.stopPromise) {
115
+ const activeStop = (async () => {
116
+ if (childHasExited(this.child))
117
+ return;
118
+ const current = await projectProcessFingerprint(this.pid).catch(() => "");
119
+ if (shouldRefuseProcessSignal(this.child, current, this.fingerprint)) {
120
+ throw new GodotMcpException({
121
+ code: "CONFLICT",
122
+ message: "Owned project process fingerprint changed; refusing to signal",
123
+ retryable: false,
124
+ correlationId: this.fingerprint,
125
+ partialEffects: false,
126
+ rollback: "not_attempted",
127
+ });
128
+ }
129
+ if (childHasExited(this.child))
130
+ return;
131
+ this.child.kill("SIGTERM");
132
+ const stopped = await Promise.race([
133
+ waitForExit(this.child).then(() => true),
134
+ new Promise((resolveTimeout) => setTimeout(() => resolveTimeout(false), graceMs)),
135
+ ]);
136
+ if (!stopped && !childHasExited(this.child)) {
137
+ const beforeKill = await projectProcessFingerprint(this.pid).catch(() => "");
138
+ if (shouldRefuseProcessSignal(this.child, beforeKill, this.fingerprint))
139
+ throw new Error("Owned project process fingerprint changed before escalation");
140
+ if (childHasExited(this.child))
141
+ return;
142
+ this.child.kill("SIGKILL");
143
+ await waitForExit(this.child);
144
+ }
145
+ })();
146
+ this.stopPromise = activeStop;
147
+ void activeStop.catch(() => {
148
+ if (this.stopPromise === activeStop)
149
+ this.stopPromise = undefined;
150
+ });
151
+ }
152
+ return this.stopPromise;
153
+ }
154
+ }
155
+ export async function recoverOwnedProjectProcess(pid, fingerprint) {
156
+ const current = await projectProcessFingerprint(pid).catch(() => "");
157
+ if (!current)
158
+ return "missing";
159
+ if (current !== fingerprint)
160
+ return "ambiguous";
161
+ try {
162
+ process.kill(pid, "SIGTERM");
163
+ }
164
+ catch {
165
+ return "ambiguous";
166
+ }
167
+ for (let attempt = 0; attempt < 40; attempt += 1) {
168
+ await new Promise((resolveWait) => setTimeout(resolveWait, 50));
169
+ const observed = await projectProcessFingerprint(pid).catch(() => "");
170
+ if (!observed)
171
+ return "stopped";
172
+ if (observed !== fingerprint)
173
+ return "ambiguous";
174
+ }
175
+ const beforeKill = await projectProcessFingerprint(pid).catch(() => "");
176
+ if (!beforeKill)
177
+ return "stopped";
178
+ if (beforeKill !== fingerprint)
179
+ return "ambiguous";
180
+ try {
181
+ process.kill(pid, "SIGKILL");
182
+ }
183
+ catch {
184
+ return "ambiguous";
185
+ }
186
+ for (let attempt = 0; attempt < 40; attempt += 1) {
187
+ await new Promise((resolveWait) => setTimeout(resolveWait, 50));
188
+ const observed = await projectProcessFingerprint(pid).catch(() => "");
189
+ if (!observed)
190
+ return "stopped";
191
+ if (observed !== fingerprint)
192
+ return "ambiguous";
193
+ }
194
+ return "ambiguous";
195
+ }
196
+ //# sourceMappingURL=projectProcess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectProcess.js","sourceRoot":"","sources":["../../src/project/projectProcess.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { ProjectOperationInput } from "@godot-mcp/protocol";
2
+ import type { ProjectJobService } from "./projectJobService.js";
3
+ import type { ProjectMutationService } from "./projectMutationService.js";
4
+ export declare class ProjectService {
5
+ private readonly mutations;
6
+ private readonly jobs;
7
+ constructor(mutations: ProjectMutationService, jobs: ProjectJobService);
8
+ execute(input: ProjectOperationInput, correlationId: string): Promise<{
9
+ data: unknown;
10
+ evidence?: string[];
11
+ audit?: {
12
+ targetIdentities: unknown[];
13
+ preconditions: unknown[];
14
+ idempotencyKeySha256: string | null;
15
+ partialEffects: boolean;
16
+ rollback: "not_needed" | "succeeded" | "failed" | "not_attempted";
17
+ };
18
+ }>;
19
+ }
20
+ //# sourceMappingURL=projectService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectService.d.ts","sourceRoot":"","sources":["../../src/project/projectService.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAE1E,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,SAAS;IAA0B,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAxD,SAAS,EAAE,sBAAsB,EAAmB,IAAI,EAAE,iBAAiB;IAElG,OAAO,CAAC,KAAK,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;QAC1E,IAAI,EAAE,OAAO,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,KAAK,CAAC,EAAE;YAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC;YAAC,aAAa,EAAE,OAAO,EAAE,CAAC;YAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;YAAC,cAAc,EAAE,OAAO,CAAC;YAAC,QAAQ,EAAE,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,eAAe,CAAA;SAAE,CAAC;KACpM,CAAC;CAsBH"}
@@ -0,0 +1,35 @@
1
+ import { createHash } from "node:crypto";
2
+ export class ProjectService {
3
+ mutations;
4
+ jobs;
5
+ constructor(mutations, jobs) {
6
+ this.mutations = mutations;
7
+ this.jobs = jobs;
8
+ }
9
+ async execute(input, correlationId) {
10
+ if (input.operation === "settings_apply" || input.operation === "plugin_set") {
11
+ const result = await this.mutations.execute(input, correlationId);
12
+ return {
13
+ data: result,
14
+ audit: {
15
+ targetIdentities: input.operation === "settings_apply"
16
+ ? result.operation === "settings_apply" ? result.changes.map((change) => change.settingNameSha256) : []
17
+ : result.operation === "plugin_set" ? [result.pluginSha256] : [],
18
+ preconditions: [],
19
+ idempotencyKeySha256: createHash("sha256").update(input.idempotencyKey).digest("hex"),
20
+ partialEffects: false,
21
+ rollback: result.rollback,
22
+ },
23
+ };
24
+ }
25
+ if (input.operation === "import_start" || input.operation === "run_start" || input.operation === "build_start" || input.operation === "export_start")
26
+ return { data: this.jobs.start(input) };
27
+ if (input.operation === "job_status")
28
+ return { data: this.jobs.status(input.jobToken) };
29
+ if (input.operation === "job_cancel")
30
+ return { data: this.jobs.cancel(input.jobToken) };
31
+ const result = this.jobs.result(input.jobToken);
32
+ return { data: result, evidence: result.evidence };
33
+ }
34
+ }
35
+ //# sourceMappingURL=projectService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectService.js","sourceRoot":"","sources":["../../src/project/projectService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOzC,MAAM,OAAO,cAAc;IACI;IAAoD;IAAjF,YAA6B,SAAiC,EAAmB,IAAuB;QAA3E,cAAS,GAAT,SAAS,CAAwB;QAAmB,SAAI,GAAJ,IAAI,CAAmB;IAAG,CAAC;IAE5G,KAAK,CAAC,OAAO,CAAC,KAA4B,EAAE,aAAqB;QAK/D,IAAI,KAAK,CAAC,SAAS,KAAK,gBAAgB,IAAI,KAAK,CAAC,SAAS,KAAK,YAAY,EAAE,CAAC;YAC7E,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;YAClE,OAAO;gBACL,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE;oBACL,gBAAgB,EAAE,KAAK,CAAC,SAAS,KAAK,gBAAgB;wBACpD,CAAC,CAAC,MAAM,CAAC,SAAS,KAAK,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE;wBACvG,CAAC,CAAC,MAAM,CAAC,SAAS,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE;oBAClE,aAAa,EAAE,EAAE;oBACjB,oBAAoB,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;oBACrF,cAAc,EAAE,KAAK;oBACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;iBAC1B;aACF,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,SAAS,KAAK,cAAc,IAAI,KAAK,CAAC,SAAS,KAAK,WAAW,IAAI,KAAK,CAAC,SAAS,KAAK,aAAa,IAAI,KAAK,CAAC,SAAS,KAAK,cAAc;YAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9L,IAAI,KAAK,CAAC,SAAS,KAAK,YAAY;YAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxF,IAAI,KAAK,CAAC,SAAS,KAAK,YAAY;YAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAChD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;IACrD,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ export declare function readSecureJournal(path: string, maxBytes: number): Promise<string | null>;
2
+ export declare function appendSecureJournal(path: string, line: string): Promise<void>;
3
+ //# sourceMappingURL=secureJournalFile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secureJournalFile.d.ts","sourceRoot":"","sources":["../../src/project/secureJournalFile.ts"],"names":[],"mappings":"AAyBA,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAW9F;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQnF"}