@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.
- package/LICENSE +21 -0
- package/README.md +105 -2
- package/dist/audit/jsonlAuditSink.d.ts +33 -0
- package/dist/audit/jsonlAuditSink.d.ts.map +1 -0
- package/dist/audit/jsonlAuditSink.js +57 -0
- package/dist/audit/jsonlAuditSink.js.map +1 -0
- package/dist/audit/redact.d.ts +2 -0
- package/dist/audit/redact.d.ts.map +1 -0
- package/dist/audit/redact.js +44 -0
- package/dist/audit/redact.js.map +1 -0
- package/dist/auth/pairingDescriptor.d.ts +44 -0
- package/dist/auth/pairingDescriptor.d.ts.map +1 -0
- package/dist/auth/pairingDescriptor.js +91 -0
- package/dist/auth/pairingDescriptor.js.map +1 -0
- package/dist/auth/runtimeDirectory.d.ts +3 -0
- package/dist/auth/runtimeDirectory.d.ts.map +1 -0
- package/dist/auth/runtimeDirectory.js +30 -0
- package/dist/auth/runtimeDirectory.js.map +1 -0
- package/dist/auth/sessionCrypto.d.ts +18 -0
- package/dist/auth/sessionCrypto.d.ts.map +1 -0
- package/dist/auth/sessionCrypto.js +118 -0
- package/dist/auth/sessionCrypto.js.map +1 -0
- package/dist/editor/editorMutationService.d.ts +21 -0
- package/dist/editor/editorMutationService.d.ts.map +1 -0
- package/dist/editor/editorMutationService.js +120 -0
- package/dist/editor/editorMutationService.js.map +1 -0
- package/dist/editor/mutationLedger.d.ts +30 -0
- package/dist/editor/mutationLedger.d.ts.map +1 -0
- package/dist/editor/mutationLedger.js +133 -0
- package/dist/editor/mutationLedger.js.map +1 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +23 -0
- package/dist/errors.js.map +1 -0
- package/dist/evidence/evidenceStore.d.ts +63 -0
- package/dist/evidence/evidenceStore.d.ts.map +1 -0
- package/dist/evidence/evidenceStore.js +350 -0
- package/dist/evidence/evidenceStore.js.map +1 -0
- package/dist/extensions/extensionRegistry.d.ts +33 -0
- package/dist/extensions/extensionRegistry.d.ts.map +1 -0
- package/dist/extensions/extensionRegistry.js +37 -0
- package/dist/extensions/extensionRegistry.js.map +1 -0
- package/dist/help/coreHelp.d.ts +10 -0
- package/dist/help/coreHelp.d.ts.map +1 -0
- package/dist/help/coreHelp.js +82 -0
- package/dist/help/coreHelp.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/policy/authorize.d.ts +5 -0
- package/dist/policy/authorize.d.ts.map +1 -0
- package/dist/policy/authorize.js +19 -0
- package/dist/policy/authorize.js.map +1 -0
- package/dist/policy/capabilities.d.ts +36 -0
- package/dist/policy/capabilities.d.ts.map +1 -0
- package/dist/policy/capabilities.js +129 -0
- package/dist/policy/capabilities.js.map +1 -0
- package/dist/project/artifactStore.d.ts +32 -0
- package/dist/project/artifactStore.d.ts.map +1 -0
- package/dist/project/artifactStore.js +172 -0
- package/dist/project/artifactStore.js.map +1 -0
- package/dist/project/pathPolicy.d.ts +4 -0
- package/dist/project/pathPolicy.d.ts.map +1 -0
- package/dist/project/pathPolicy.js +74 -0
- package/dist/project/pathPolicy.js.map +1 -0
- package/dist/project/projectConfig.d.ts +10 -0
- package/dist/project/projectConfig.d.ts.map +1 -0
- package/dist/project/projectConfig.js +63 -0
- package/dist/project/projectConfig.js.map +1 -0
- package/dist/project/projectIdentity.d.ts +8 -0
- package/dist/project/projectIdentity.d.ts.map +1 -0
- package/dist/project/projectIdentity.js +58 -0
- package/dist/project/projectIdentity.js.map +1 -0
- package/dist/project/projectJobJournal.d.ts +49 -0
- package/dist/project/projectJobJournal.d.ts.map +1 -0
- package/dist/project/projectJobJournal.js +67 -0
- package/dist/project/projectJobJournal.js.map +1 -0
- package/dist/project/projectJobService.d.ts +52 -0
- package/dist/project/projectJobService.d.ts.map +1 -0
- package/dist/project/projectJobService.js +289 -0
- package/dist/project/projectJobService.js.map +1 -0
- package/dist/project/projectMutationService.d.ts +40 -0
- package/dist/project/projectMutationService.d.ts.map +1 -0
- package/dist/project/projectMutationService.js +145 -0
- package/dist/project/projectMutationService.js.map +1 -0
- package/dist/project/projectPreflight.d.ts +7 -0
- package/dist/project/projectPreflight.d.ts.map +1 -0
- package/dist/project/projectPreflight.js +50 -0
- package/dist/project/projectPreflight.js.map +1 -0
- package/dist/project/projectProcess.d.ts +40 -0
- package/dist/project/projectProcess.d.ts.map +1 -0
- package/dist/project/projectProcess.js +196 -0
- package/dist/project/projectProcess.js.map +1 -0
- package/dist/project/projectService.d.ts +20 -0
- package/dist/project/projectService.d.ts.map +1 -0
- package/dist/project/projectService.js +35 -0
- package/dist/project/projectService.js.map +1 -0
- package/dist/project/secureJournalFile.d.ts +3 -0
- package/dist/project/secureJournalFile.d.ts.map +1 -0
- package/dist/project/secureJournalFile.js +56 -0
- package/dist/project/secureJournalFile.js.map +1 -0
- package/dist/runtime/debugTokenStore.d.ts +41 -0
- package/dist/runtime/debugTokenStore.d.ts.map +1 -0
- package/dist/runtime/debugTokenStore.js +105 -0
- package/dist/runtime/debugTokenStore.js.map +1 -0
- package/dist/runtime/debuggerClient.d.ts +14 -0
- package/dist/runtime/debuggerClient.d.ts.map +1 -0
- package/dist/runtime/debuggerClient.js +21 -0
- package/dist/runtime/debuggerClient.js.map +1 -0
- package/dist/runtime/inputReceipt.d.ts +15 -0
- package/dist/runtime/inputReceipt.d.ts.map +1 -0
- package/dist/runtime/inputReceipt.js +36 -0
- package/dist/runtime/inputReceipt.js.map +1 -0
- package/dist/runtime/runtimeDescriptor.d.ts +50 -0
- package/dist/runtime/runtimeDescriptor.d.ts.map +1 -0
- package/dist/runtime/runtimeDescriptor.js +175 -0
- package/dist/runtime/runtimeDescriptor.js.map +1 -0
- package/dist/runtime/runtimeProcess.d.ts +39 -0
- package/dist/runtime/runtimeProcess.d.ts.map +1 -0
- package/dist/runtime/runtimeProcess.js +180 -0
- package/dist/runtime/runtimeProcess.js.map +1 -0
- package/dist/runtime/runtimeService.d.ts +130 -0
- package/dist/runtime/runtimeService.d.ts.map +1 -0
- package/dist/runtime/runtimeService.js +919 -0
- package/dist/runtime/runtimeService.js.map +1 -0
- package/dist/session/sessionService.d.ts +52 -0
- package/dist/session/sessionService.d.ts.map +1 -0
- package/dist/session/sessionService.js +72 -0
- package/dist/session/sessionService.js.map +1 -0
- package/dist/unsafe/unsafeFixtureAuthority.d.ts +27 -0
- package/dist/unsafe/unsafeFixtureAuthority.d.ts.map +1 -0
- package/dist/unsafe/unsafeFixtureAuthority.js +130 -0
- package/dist/unsafe/unsafeFixtureAuthority.js.map +1 -0
- package/dist/unsafe/unsafeFixtureProcess.d.ts +30 -0
- package/dist/unsafe/unsafeFixtureProcess.d.ts.map +1 -0
- package/dist/unsafe/unsafeFixtureProcess.js +119 -0
- package/dist/unsafe/unsafeFixtureProcess.js.map +1 -0
- package/dist/unsafe/unsafeFixtureService.d.ts +41 -0
- package/dist/unsafe/unsafeFixtureService.d.ts.map +1 -0
- package/dist/unsafe/unsafeFixtureService.js +162 -0
- package/dist/unsafe/unsafeFixtureService.js.map +1 -0
- package/dist/visual/pngComparison.d.ts +12 -0
- package/dist/visual/pngComparison.d.ts.map +1 -0
- package/dist/visual/pngComparison.js +136 -0
- package/dist/visual/pngComparison.js.map +1 -0
- package/dist/visual/scenarioService.d.ts +50 -0
- package/dist/visual/scenarioService.d.ts.map +1 -0
- package/dist/visual/scenarioService.js +421 -0
- package/dist/visual/scenarioService.js.map +1 -0
- package/dist/visual/visualService.d.ts +27 -0
- package/dist/visual/visualService.d.ts.map +1 -0
- package/dist/visual/visualService.js +70 -0
- package/dist/visual/visualService.js.map +1 -0
- package/package.json +26 -6
- package/index.js +0 -1
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { link, lstat, mkdir, open, readFile, rename, rm } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { canonicalJson } from "@godot-mcp/protocol";
|
|
5
|
+
import { GodotMcpException } from "../errors.js";
|
|
6
|
+
const MAX_PNG_BYTES = 8 * 1024 * 1024;
|
|
7
|
+
const MAX_JSON_BYTES = 1024 * 1024;
|
|
8
|
+
const PNG_SIGNATURE = Buffer.from("89504e470d0a1a0a", "hex");
|
|
9
|
+
const SESSION_PATTERN = /^session_[A-Za-z0-9_-]{8,128}$/;
|
|
10
|
+
const BASELINE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
|
|
11
|
+
const OBSERVATION_URI_PATTERN = /^godot-mcp:\/\/evidence\/([a-f0-9]{64})\/observations\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;
|
|
12
|
+
function evidenceError(code, message) {
|
|
13
|
+
return new GodotMcpException({
|
|
14
|
+
code,
|
|
15
|
+
message,
|
|
16
|
+
retryable: false,
|
|
17
|
+
correlationId: randomUUID(),
|
|
18
|
+
partialEffects: false,
|
|
19
|
+
rollback: "not_needed",
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
async function atomicWrite(path, contents) {
|
|
23
|
+
const temporary = `${path}.tmp-${randomUUID()}`;
|
|
24
|
+
const handle = await open(temporary, "wx", 0o600);
|
|
25
|
+
try {
|
|
26
|
+
await handle.writeFile(contents);
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
await handle.close();
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
await rename(temporary, path);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
await rm(temporary, { force: true });
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function atomicWriteOnce(path, contents) {
|
|
40
|
+
const temporary = `${path}.tmp-${randomUUID()}`;
|
|
41
|
+
const handle = await open(temporary, "wx", 0o600);
|
|
42
|
+
try {
|
|
43
|
+
await handle.writeFile(contents);
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
await handle.close();
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
await link(temporary, path);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
if (error.code === "EEXIST")
|
|
54
|
+
return false;
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
await rm(temporary, { force: true });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function readPlainFile(path) {
|
|
62
|
+
const metadata = await lstat(path).catch(() => undefined);
|
|
63
|
+
if (!metadata)
|
|
64
|
+
throw evidenceError("PRECONDITION_FAILED", "Visual evidence is unavailable");
|
|
65
|
+
if (metadata.isSymbolicLink() || !metadata.isFile()) {
|
|
66
|
+
throw evidenceError("PATH_DENIED", "Visual evidence must be a regular non-symlink file");
|
|
67
|
+
}
|
|
68
|
+
return readFile(path);
|
|
69
|
+
}
|
|
70
|
+
async function readOptionalPlainFile(path) {
|
|
71
|
+
return readPlainFile(path).catch((error) => {
|
|
72
|
+
if (error instanceof GodotMcpException && error.code === "PRECONDITION_FAILED")
|
|
73
|
+
return undefined;
|
|
74
|
+
throw error;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
async function plainDirectory(root, segments, create) {
|
|
78
|
+
let current = root;
|
|
79
|
+
const rootMetadata = await lstat(current).catch(() => undefined);
|
|
80
|
+
if (!rootMetadata || rootMetadata.isSymbolicLink() || !rootMetadata.isDirectory()) {
|
|
81
|
+
throw evidenceError("PATH_DENIED", "Evidence root must be a regular non-symlink directory");
|
|
82
|
+
}
|
|
83
|
+
for (const segment of segments) {
|
|
84
|
+
current = join(current, segment);
|
|
85
|
+
let metadata = await lstat(current).catch(() => undefined);
|
|
86
|
+
if (!metadata && create) {
|
|
87
|
+
await mkdir(current, { mode: 0o700 }).catch(async (error) => {
|
|
88
|
+
if (!(await lstat(current).catch(() => undefined)))
|
|
89
|
+
throw error;
|
|
90
|
+
});
|
|
91
|
+
metadata = await lstat(current).catch(() => undefined);
|
|
92
|
+
}
|
|
93
|
+
if (!metadata)
|
|
94
|
+
throw evidenceError("PRECONDITION_FAILED", "Visual evidence directory is unavailable");
|
|
95
|
+
if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
|
|
96
|
+
throw evidenceError("PATH_DENIED", "Visual evidence directories must not be symbolic links");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return current;
|
|
100
|
+
}
|
|
101
|
+
function observationIdentity(uri) {
|
|
102
|
+
const match = OBSERVATION_URI_PATTERN.exec(uri);
|
|
103
|
+
if (!match)
|
|
104
|
+
throw evidenceError("PATH_DENIED", "Evidence observation URI is invalid");
|
|
105
|
+
return { sha256: match[1], observationId: match[2] };
|
|
106
|
+
}
|
|
107
|
+
function validateSessionId(sessionId) {
|
|
108
|
+
if (!SESSION_PATTERN.test(sessionId))
|
|
109
|
+
throw evidenceError("PATH_DENIED", "Evidence session identifier is invalid");
|
|
110
|
+
}
|
|
111
|
+
function validateBaselineName(name) {
|
|
112
|
+
if (!BASELINE_NAME_PATTERN.test(name))
|
|
113
|
+
throw evidenceError("PATH_DENIED", "Visual baseline name is invalid");
|
|
114
|
+
}
|
|
115
|
+
function parsePngBaselineManifest(value, expectedName) {
|
|
116
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
117
|
+
throw evidenceError("CONFLICT", "Visual baseline manifest is malformed");
|
|
118
|
+
}
|
|
119
|
+
const manifest = value;
|
|
120
|
+
const keys = Object.keys(manifest).sort();
|
|
121
|
+
const expectedKeys = [
|
|
122
|
+
"byteLength", "comparisonContractVersion", "createdAtUnixMs", "height", "mimeType", "name",
|
|
123
|
+
"schemaVersion", "sha256", "sourceObservationSha256", "width",
|
|
124
|
+
].sort();
|
|
125
|
+
if (JSON.stringify(keys) !== JSON.stringify(expectedKeys) ||
|
|
126
|
+
manifest.schemaVersion !== 1 ||
|
|
127
|
+
manifest.comparisonContractVersion !== 1 ||
|
|
128
|
+
manifest.name !== expectedName ||
|
|
129
|
+
typeof manifest.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(manifest.sha256) ||
|
|
130
|
+
manifest.mimeType !== "image/png" ||
|
|
131
|
+
!Number.isInteger(manifest.byteLength) || Number(manifest.byteLength) < 1 || Number(manifest.byteLength) > MAX_PNG_BYTES ||
|
|
132
|
+
!Number.isInteger(manifest.width) || Number(manifest.width) < 1 || Number(manifest.width) > 2048 ||
|
|
133
|
+
!Number.isInteger(manifest.height) || Number(manifest.height) < 1 || Number(manifest.height) > 2048 ||
|
|
134
|
+
typeof manifest.sourceObservationSha256 !== "string" || !/^[a-f0-9]{64}$/.test(manifest.sourceObservationSha256) ||
|
|
135
|
+
!Number.isInteger(manifest.createdAtUnixMs) || Number(manifest.createdAtUnixMs) < 0)
|
|
136
|
+
throw evidenceError("CONFLICT", "Visual baseline manifest is malformed");
|
|
137
|
+
return manifest;
|
|
138
|
+
}
|
|
139
|
+
export class EvidenceStore {
|
|
140
|
+
projectRoot;
|
|
141
|
+
constructor(projectRoot) {
|
|
142
|
+
this.projectRoot = projectRoot;
|
|
143
|
+
}
|
|
144
|
+
async putPng(sessionId, png, metadata) {
|
|
145
|
+
validateSessionId(sessionId);
|
|
146
|
+
if (png.byteLength > MAX_PNG_BYTES) {
|
|
147
|
+
throw evidenceError("PAYLOAD_TOO_LARGE", "PNG evidence exceeds 8 MiB");
|
|
148
|
+
}
|
|
149
|
+
if (png.byteLength < PNG_SIGNATURE.length || !Buffer.from(png).subarray(0, 8).equals(PNG_SIGNATURE)) {
|
|
150
|
+
throw evidenceError("INVALID_REQUEST", "Evidence bytes are not a PNG");
|
|
151
|
+
}
|
|
152
|
+
const sha256 = createHash("sha256").update(png).digest("hex");
|
|
153
|
+
const directory = await plainDirectory(this.projectRoot, [".godot", "evidence", "godot-mcp", "sessions", sessionId], true);
|
|
154
|
+
const path = join(directory, `${sha256}.png`);
|
|
155
|
+
const existing = await readOptionalPlainFile(path);
|
|
156
|
+
if (existing) {
|
|
157
|
+
const existingSha256 = createHash("sha256").update(existing).digest("hex");
|
|
158
|
+
if (existingSha256 !== sha256) {
|
|
159
|
+
throw evidenceError("CONFLICT", "Existing evidence digest conflicts");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
await atomicWrite(path, png);
|
|
164
|
+
}
|
|
165
|
+
const metadataPath = join(directory, `${sha256}.json`);
|
|
166
|
+
const metadataContents = `${JSON.stringify({
|
|
167
|
+
sha256,
|
|
168
|
+
mimeType: "image/png",
|
|
169
|
+
byteLength: png.byteLength,
|
|
170
|
+
width: metadata.width,
|
|
171
|
+
height: metadata.height,
|
|
172
|
+
})}\n`;
|
|
173
|
+
if (!(await readOptionalPlainFile(metadataPath))) {
|
|
174
|
+
await atomicWrite(metadataPath, metadataContents);
|
|
175
|
+
}
|
|
176
|
+
const observationId = randomUUID();
|
|
177
|
+
const observationDirectory = await plainDirectory(this.projectRoot, [".godot", "evidence", "godot-mcp", "sessions", sessionId, `${sha256}.observations`], true);
|
|
178
|
+
const observationPath = join(observationDirectory, `${observationId}.json`);
|
|
179
|
+
await atomicWrite(observationPath, `${JSON.stringify({
|
|
180
|
+
...metadata,
|
|
181
|
+
observationId,
|
|
182
|
+
sha256,
|
|
183
|
+
mimeType: "image/png",
|
|
184
|
+
byteLength: png.byteLength,
|
|
185
|
+
})}\n`);
|
|
186
|
+
return {
|
|
187
|
+
uri: `godot-mcp://evidence/${sha256}`,
|
|
188
|
+
observationUri: `godot-mcp://evidence/${sha256}/observations/${observationId}`,
|
|
189
|
+
sha256,
|
|
190
|
+
mimeType: "image/png",
|
|
191
|
+
byteLength: png.byteLength,
|
|
192
|
+
path,
|
|
193
|
+
observationPath,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
async readSessionPngObservation(sessionId, observationUri) {
|
|
197
|
+
validateSessionId(sessionId);
|
|
198
|
+
const { sha256, observationId } = observationIdentity(observationUri);
|
|
199
|
+
let directory;
|
|
200
|
+
let observationDirectory;
|
|
201
|
+
try {
|
|
202
|
+
directory = await plainDirectory(this.projectRoot, [".godot", "evidence", "godot-mcp", "sessions", sessionId], false);
|
|
203
|
+
observationDirectory = await plainDirectory(this.projectRoot, [".godot", "evidence", "godot-mcp", "sessions", sessionId, `${sha256}.observations`], false);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
if (error instanceof GodotMcpException && error.code === "PRECONDITION_FAILED") {
|
|
207
|
+
throw evidenceError("STALE_HANDLE", "Evidence observation does not belong to the current session");
|
|
208
|
+
}
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
const observationPath = join(observationDirectory, `${observationId}.json`);
|
|
212
|
+
const observationBytes = await readPlainFile(observationPath).catch((error) => {
|
|
213
|
+
if (error instanceof GodotMcpException && error.code === "PRECONDITION_FAILED") {
|
|
214
|
+
throw evidenceError("STALE_HANDLE", "Evidence observation does not belong to the current session");
|
|
215
|
+
}
|
|
216
|
+
throw error;
|
|
217
|
+
});
|
|
218
|
+
let metadata;
|
|
219
|
+
try {
|
|
220
|
+
const parsed = JSON.parse(observationBytes.toString("utf8"));
|
|
221
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
222
|
+
throw new TypeError("not an object");
|
|
223
|
+
metadata = parsed;
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
throw evidenceError("CONFLICT", "Evidence observation metadata is malformed");
|
|
227
|
+
}
|
|
228
|
+
if (metadata.observationId !== observationId ||
|
|
229
|
+
metadata.sha256 !== sha256 ||
|
|
230
|
+
metadata.mimeType !== "image/png" ||
|
|
231
|
+
!Number.isInteger(metadata.byteLength) ||
|
|
232
|
+
!Number.isInteger(metadata.width) || Number(metadata.width) < 1 || Number(metadata.width) > 2048 ||
|
|
233
|
+
!Number.isInteger(metadata.height) || Number(metadata.height) < 1 || Number(metadata.height) > 2048)
|
|
234
|
+
throw evidenceError("CONFLICT", "Evidence observation metadata conflicts with its URI");
|
|
235
|
+
const data = await readPlainFile(join(directory, `${sha256}.png`));
|
|
236
|
+
const actualSha256 = createHash("sha256").update(data).digest("hex");
|
|
237
|
+
if (actualSha256 !== sha256 || data.byteLength !== metadata.byteLength) {
|
|
238
|
+
throw evidenceError("CONFLICT", "Evidence PNG digest or length conflicts with its observation");
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
data,
|
|
242
|
+
sha256,
|
|
243
|
+
mimeType: "image/png",
|
|
244
|
+
byteLength: data.byteLength,
|
|
245
|
+
width: Number(metadata.width),
|
|
246
|
+
height: Number(metadata.height),
|
|
247
|
+
observationUri: observationUri,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
async putJson(sessionId, value, metadata) {
|
|
251
|
+
validateSessionId(sessionId);
|
|
252
|
+
const contents = Buffer.from(canonicalJson(value), "utf8");
|
|
253
|
+
if (contents.byteLength > MAX_JSON_BYTES)
|
|
254
|
+
throw evidenceError("PAYLOAD_TOO_LARGE", "JSON evidence exceeds one MiB");
|
|
255
|
+
const sha256 = createHash("sha256").update(contents).digest("hex");
|
|
256
|
+
const directory = await plainDirectory(this.projectRoot, [".godot", "evidence", "godot-mcp", "sessions", sessionId], true);
|
|
257
|
+
const path = join(directory, `${sha256}.json`);
|
|
258
|
+
const existing = await readOptionalPlainFile(path);
|
|
259
|
+
if (existing && !existing.equals(contents))
|
|
260
|
+
throw evidenceError("CONFLICT", "Existing JSON evidence digest conflicts");
|
|
261
|
+
if (!existing)
|
|
262
|
+
await atomicWrite(path, contents);
|
|
263
|
+
const observationId = randomUUID();
|
|
264
|
+
const observationDirectory = await plainDirectory(this.projectRoot, [".godot", "evidence", "godot-mcp", "sessions", sessionId, `${sha256}.observations`], true);
|
|
265
|
+
const observationPath = join(observationDirectory, `${observationId}.json`);
|
|
266
|
+
await atomicWrite(observationPath, `${canonicalJson({
|
|
267
|
+
...metadata,
|
|
268
|
+
observationId,
|
|
269
|
+
sha256,
|
|
270
|
+
mimeType: "application/json",
|
|
271
|
+
byteLength: contents.byteLength,
|
|
272
|
+
})}\n`);
|
|
273
|
+
return {
|
|
274
|
+
uri: `godot-mcp://evidence/${sha256}`,
|
|
275
|
+
observationUri: `godot-mcp://evidence/${sha256}/observations/${observationId}`,
|
|
276
|
+
sha256,
|
|
277
|
+
mimeType: "application/json",
|
|
278
|
+
byteLength: contents.byteLength,
|
|
279
|
+
path,
|
|
280
|
+
observationPath,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
async createPngBaseline(sessionId, name, observationUri, createdAtUnixMs = Date.now()) {
|
|
284
|
+
validateBaselineName(name);
|
|
285
|
+
const observation = await this.readSessionPngObservation(sessionId, observationUri);
|
|
286
|
+
const directory = await plainDirectory(this.projectRoot, [".godot", "evidence", "godot-mcp", "baselines", name], true);
|
|
287
|
+
const manifestPath = join(directory, "manifest.json");
|
|
288
|
+
const existingManifest = await readOptionalPlainFile(manifestPath);
|
|
289
|
+
if (existingManifest) {
|
|
290
|
+
let existing;
|
|
291
|
+
try {
|
|
292
|
+
existing = parsePngBaselineManifest(JSON.parse(existingManifest.toString("utf8")), name);
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
if (error instanceof GodotMcpException)
|
|
296
|
+
throw error;
|
|
297
|
+
throw evidenceError("CONFLICT", "Visual baseline manifest is malformed");
|
|
298
|
+
}
|
|
299
|
+
if (existing.sha256 !== observation.sha256)
|
|
300
|
+
throw evidenceError("CONFLICT", "Visual baseline name already refers to different evidence");
|
|
301
|
+
await this.readPngBaselineData(name);
|
|
302
|
+
return existing;
|
|
303
|
+
}
|
|
304
|
+
const manifest = {
|
|
305
|
+
schemaVersion: 1,
|
|
306
|
+
comparisonContractVersion: 1,
|
|
307
|
+
name,
|
|
308
|
+
sha256: observation.sha256,
|
|
309
|
+
mimeType: "image/png",
|
|
310
|
+
byteLength: observation.byteLength,
|
|
311
|
+
width: observation.width,
|
|
312
|
+
height: observation.height,
|
|
313
|
+
sourceObservationSha256: observation.sha256,
|
|
314
|
+
createdAtUnixMs,
|
|
315
|
+
};
|
|
316
|
+
const pngPath = join(directory, `${observation.sha256}.png`);
|
|
317
|
+
if (!(await readOptionalPlainFile(pngPath)))
|
|
318
|
+
await atomicWrite(pngPath, observation.data);
|
|
319
|
+
if (await atomicWriteOnce(manifestPath, `${canonicalJson(manifest)}\n`))
|
|
320
|
+
return manifest;
|
|
321
|
+
const winner = await this.readPngBaselineData(name);
|
|
322
|
+
if (winner.manifest.sha256 !== observation.sha256) {
|
|
323
|
+
throw evidenceError("CONFLICT", "Visual baseline name already refers to different evidence");
|
|
324
|
+
}
|
|
325
|
+
return winner.manifest;
|
|
326
|
+
}
|
|
327
|
+
async readPngBaseline(name) {
|
|
328
|
+
return (await this.readPngBaselineData(name)).manifest;
|
|
329
|
+
}
|
|
330
|
+
async readPngBaselineData(name) {
|
|
331
|
+
validateBaselineName(name);
|
|
332
|
+
const directory = await plainDirectory(this.projectRoot, [".godot", "evidence", "godot-mcp", "baselines", name], false);
|
|
333
|
+
const manifestBytes = await readPlainFile(join(directory, "manifest.json"));
|
|
334
|
+
let parsed;
|
|
335
|
+
try {
|
|
336
|
+
parsed = JSON.parse(manifestBytes.toString("utf8"));
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
throw evidenceError("CONFLICT", "Visual baseline manifest is malformed");
|
|
340
|
+
}
|
|
341
|
+
const manifest = parsePngBaselineManifest(parsed, name);
|
|
342
|
+
const data = await readPlainFile(join(directory, `${manifest.sha256}.png`));
|
|
343
|
+
const digest = createHash("sha256").update(data).digest("hex");
|
|
344
|
+
if (digest !== manifest.sha256 || data.byteLength !== manifest.byteLength) {
|
|
345
|
+
throw evidenceError("CONFLICT", "Visual baseline bytes conflict with its manifest");
|
|
346
|
+
}
|
|
347
|
+
return { manifest, data };
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
//# sourceMappingURL=evidenceStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidenceStore.js","sourceRoot":"","sources":["../../src/evidence/evidenceStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { ProjectIdentity } from "@godot-mcp/protocol";
|
|
3
|
+
import type { CommandPolicy, SessionGrants } from "../policy/capabilities.js";
|
|
4
|
+
export interface ExtensionEvidenceWriter {
|
|
5
|
+
putJson(value: unknown, metadata: Record<string, unknown>): Promise<string>;
|
|
6
|
+
}
|
|
7
|
+
export interface ExtensionContext {
|
|
8
|
+
readonly project: Readonly<ProjectIdentity>;
|
|
9
|
+
readonly correlationId: string;
|
|
10
|
+
readonly evidence: ExtensionEvidenceWriter;
|
|
11
|
+
}
|
|
12
|
+
export interface ExtensionDefinition<Input = unknown, Output = unknown> {
|
|
13
|
+
extension: string;
|
|
14
|
+
operation: string;
|
|
15
|
+
policy: CommandPolicy;
|
|
16
|
+
inputSchema: z.ZodType<Input>;
|
|
17
|
+
outputSchema: z.ZodType<Output>;
|
|
18
|
+
audit(input: Input): Record<string, unknown>;
|
|
19
|
+
handler(context: ExtensionContext, input: Input): Promise<Output>;
|
|
20
|
+
}
|
|
21
|
+
export declare class ExtensionRegistry {
|
|
22
|
+
private readonly definitions;
|
|
23
|
+
register<Input, Output>(definition: ExtensionDefinition<Input, Output>): void;
|
|
24
|
+
resolve(extension: string, operation: string): ExtensionDefinition;
|
|
25
|
+
visible(grants: SessionGrants): boolean;
|
|
26
|
+
list(): Array<{
|
|
27
|
+
extension: string;
|
|
28
|
+
operation: string;
|
|
29
|
+
policy: CommandPolicy;
|
|
30
|
+
}>;
|
|
31
|
+
private key;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=extensionRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensionRegistry.d.ts","sourceRoot":"","sources":["../../src/extensions/extensionRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAO9E,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7E;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;CAC5C;AAED,MAAM,WAAW,mBAAmB,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,OAAO;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC;IACtB,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACnE;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0C;IAEtE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,IAAI;IAa7E,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,mBAAmB;IAMlE,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO;IAKvC,IAAI,IAAI,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,CAAC;IAI9E,OAAO,CAAC,GAAG;CACZ"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { expandPermissionTiers } from "../policy/capabilities.js";
|
|
2
|
+
import { visibleCapabilities } from "../policy/capabilities.js";
|
|
3
|
+
const NAME = /^[a-z][a-z0-9_-]{0,63}$/;
|
|
4
|
+
const EXTENSION_POLICIES = visibleCapabilities({ tiers: ["observe", "runtime_control", "project_mutate", "project_operate"], packs: ["core", "runtime", "input", "editor", "debug", "visual", "project"] });
|
|
5
|
+
export class ExtensionRegistry {
|
|
6
|
+
definitions = new Map();
|
|
7
|
+
register(definition) {
|
|
8
|
+
if (!NAME.test(definition.extension) || !NAME.test(definition.operation))
|
|
9
|
+
throw new Error("Extension and operation names must be bounded lowercase identifiers");
|
|
10
|
+
if (definition.policy.tier === "unsafe_fixture" || definition.policy.pack === "unsafe")
|
|
11
|
+
throw new Error("Extensions cannot acquire unsafe fixture authority");
|
|
12
|
+
const knownPolicy = EXTENSION_POLICIES.find((policy) => policy.command === definition.policy.command);
|
|
13
|
+
if (!knownPolicy || knownPolicy.tier !== definition.policy.tier || knownPolicy.pack !== definition.policy.pack || knownPolicy.mutating !== definition.policy.mutating || JSON.stringify(knownPolicy.requiredPacks ?? []) !== JSON.stringify(definition.policy.requiredPacks ?? [])) {
|
|
14
|
+
throw new Error("Extension operations must use an exact existing control-plane policy");
|
|
15
|
+
}
|
|
16
|
+
const key = this.key(definition.extension, definition.operation);
|
|
17
|
+
if (this.definitions.has(key))
|
|
18
|
+
throw new Error("Duplicate extension operation");
|
|
19
|
+
const policy = Object.freeze({ ...knownPolicy, ...(knownPolicy.requiredPacks === undefined ? {} : { requiredPacks: Object.freeze([...knownPolicy.requiredPacks]) }) });
|
|
20
|
+
this.definitions.set(key, Object.freeze({ ...definition, policy }));
|
|
21
|
+
}
|
|
22
|
+
resolve(extension, operation) {
|
|
23
|
+
const definition = this.definitions.get(this.key(extension, operation));
|
|
24
|
+
if (!definition)
|
|
25
|
+
throw new Error("Extension operation is not registered at startup");
|
|
26
|
+
return definition;
|
|
27
|
+
}
|
|
28
|
+
visible(grants) {
|
|
29
|
+
const tiers = expandPermissionTiers(grants.tiers);
|
|
30
|
+
return [...this.definitions.values()].some((definition) => tiers.includes(definition.policy.tier) && (definition.policy.requiredPacks ?? [definition.policy.pack]).every((pack) => grants.packs.includes(pack)));
|
|
31
|
+
}
|
|
32
|
+
list() {
|
|
33
|
+
return [...this.definitions.values()].map(({ extension, operation, policy }) => ({ extension, operation, policy: { ...policy } }));
|
|
34
|
+
}
|
|
35
|
+
key(extension, operation) { return `${extension}\0${operation}`; }
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=extensionRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensionRegistry.js","sourceRoot":"","sources":["../../src/extensions/extensionRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type CoreHelpTopic = "session" | "capabilities" | "doctor" | "help" | "query" | "capture" | "runtime" | "runtime_capture" | "input";
|
|
2
|
+
export interface CoreHelp {
|
|
3
|
+
topic: CoreHelpTopic;
|
|
4
|
+
title: string;
|
|
5
|
+
summary: string;
|
|
6
|
+
tool: `godot_${CoreHelpTopic}`;
|
|
7
|
+
readOnly: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function getCoreHelp(topic?: CoreHelpTopic): CoreHelp;
|
|
10
|
+
//# sourceMappingURL=coreHelp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coreHelp.d.ts","sourceRoot":"","sources":["../../src/help/coreHelp.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,cAAc,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,iBAAiB,GAAG,OAAO,CAAC;AAE3I,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,aAAa,EAAE,CAAC;IAC/B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAoED,wBAAgB,WAAW,CAAC,KAAK,GAAE,aAAsB,GAAG,QAAQ,CAanE"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { GodotMcpException } from "../errors.js";
|
|
3
|
+
const HELP = {
|
|
4
|
+
session: {
|
|
5
|
+
topic: "session",
|
|
6
|
+
title: "Godot session status",
|
|
7
|
+
summary: "Returns attachment state, project identity, versions, and granted access without credentials.",
|
|
8
|
+
tool: "godot_session",
|
|
9
|
+
readOnly: true,
|
|
10
|
+
},
|
|
11
|
+
capabilities: {
|
|
12
|
+
topic: "capabilities",
|
|
13
|
+
title: "Godot capabilities",
|
|
14
|
+
summary: "Lists only operations authorized by the current permission tiers and capability packs.",
|
|
15
|
+
tool: "godot_capabilities",
|
|
16
|
+
readOnly: true,
|
|
17
|
+
},
|
|
18
|
+
doctor: {
|
|
19
|
+
topic: "doctor",
|
|
20
|
+
title: "Godot MCP doctor",
|
|
21
|
+
summary: "Combines read-only installation checks with current bridge attachment health.",
|
|
22
|
+
tool: "godot_doctor",
|
|
23
|
+
readOnly: true,
|
|
24
|
+
},
|
|
25
|
+
help: {
|
|
26
|
+
topic: "help",
|
|
27
|
+
title: "Godot MCP help",
|
|
28
|
+
summary: "Returns focused documentation for one of the read-only core tools.",
|
|
29
|
+
tool: "godot_help",
|
|
30
|
+
readOnly: true,
|
|
31
|
+
},
|
|
32
|
+
query: {
|
|
33
|
+
topic: "query",
|
|
34
|
+
title: "Query Godot editor",
|
|
35
|
+
summary: "Reads bounded editor state, open scene trees and nodes, indexed resource metadata, approved project settings, or redacted diagnostics.",
|
|
36
|
+
tool: "godot_query",
|
|
37
|
+
readOnly: true,
|
|
38
|
+
},
|
|
39
|
+
capture: {
|
|
40
|
+
topic: "capture",
|
|
41
|
+
title: "Capture Godot editor viewport",
|
|
42
|
+
summary: "Returns a bounded PNG image from the current 2D editor viewport or one of four 3D editor viewports without switching editor screens.",
|
|
43
|
+
tool: "godot_capture",
|
|
44
|
+
readOnly: true,
|
|
45
|
+
},
|
|
46
|
+
runtime: {
|
|
47
|
+
topic: "runtime",
|
|
48
|
+
title: "Control an ephemeral Godot runtime",
|
|
49
|
+
summary: "Launches and controls one authenticated MCP-owned runtime with bounded tree, node, log, wait, pause, resume, step, and stop operations.",
|
|
50
|
+
tool: "godot_runtime",
|
|
51
|
+
readOnly: false,
|
|
52
|
+
},
|
|
53
|
+
runtime_capture: {
|
|
54
|
+
topic: "runtime_capture",
|
|
55
|
+
title: "Capture an ephemeral Godot runtime",
|
|
56
|
+
summary: "Returns one to eight bounded running-game PNG frames from the authenticated MCP-owned runtime.",
|
|
57
|
+
tool: "godot_runtime_capture",
|
|
58
|
+
readOnly: false,
|
|
59
|
+
},
|
|
60
|
+
input: {
|
|
61
|
+
topic: "input",
|
|
62
|
+
title: "Automate owned runtime input",
|
|
63
|
+
summary: "Injects bounded events and frame-indexed sequences into an authenticated owned runtime. Requires explicit runtime_control and input grants; launch remains separately gated by the runtime pack. Recording is non-passive and limited to MCP-injected events.",
|
|
64
|
+
tool: "godot_input",
|
|
65
|
+
readOnly: false,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
export function getCoreHelp(topic = "help") {
|
|
69
|
+
const help = HELP[topic];
|
|
70
|
+
if (!help) {
|
|
71
|
+
throw new GodotMcpException({
|
|
72
|
+
code: "TARGET_NOT_FOUND",
|
|
73
|
+
message: `Unknown core help topic: ${String(topic)}`,
|
|
74
|
+
retryable: false,
|
|
75
|
+
correlationId: randomUUID(),
|
|
76
|
+
partialEffects: false,
|
|
77
|
+
rollback: "not_needed",
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return { ...help };
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=coreHelp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coreHelp.js","sourceRoot":"","sources":["../../src/help/coreHelp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAYjD,MAAM,IAAI,GAAoC;IAC5C,OAAO,EAAE;QACP,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,sBAAsB;QAC7B,OAAO,EAAE,+FAA+F;QACxG,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,IAAI;KACf;IACD,YAAY,EAAE;QACZ,KAAK,EAAE,cAAc;QACrB,KAAK,EAAE,oBAAoB;QAC3B,OAAO,EAAE,wFAAwF;QACjG,IAAI,EAAE,oBAAoB;QAC1B,QAAQ,EAAE,IAAI;KACf;IACD,MAAM,EAAE;QACN,KAAK,EAAE,QAAQ;QACf,KAAK,EAAE,kBAAkB;QACzB,OAAO,EAAE,+EAA+E;QACxF,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE,IAAI;KACf;IACD,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM;QACb,KAAK,EAAE,gBAAgB;QACvB,OAAO,EAAE,oEAAoE;QAC7E,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,IAAI;KACf;IACD,KAAK,EAAE;QACL,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,oBAAoB;QAC3B,OAAO,EAAE,wIAAwI;QACjJ,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE,IAAI;KACf;IACD,OAAO,EAAE;QACP,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,+BAA+B;QACtC,OAAO,EAAE,sIAAsI;QAC/I,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,IAAI;KACf;IACD,OAAO,EAAE;QACP,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,oCAAoC;QAC3C,OAAO,EAAE,yIAAyI;QAClJ,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,KAAK;KAChB;IACD,eAAe,EAAE;QACf,KAAK,EAAE,iBAAiB;QACxB,KAAK,EAAE,oCAAoC;QAC3C,OAAO,EAAE,gGAAgG;QACzG,IAAI,EAAE,uBAAuB;QAC7B,QAAQ,EAAE,KAAK;KAChB;IACD,KAAK,EAAE;QACL,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,8BAA8B;QACrC,OAAO,EAAE,+PAA+P;QACxQ,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE,KAAK;KAChB;CACF,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,QAAuB,MAAM;IACvD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,iBAAiB,CAAC;YAC1B,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,4BAA4B,MAAM,CAAC,KAAK,CAAC,EAAE;YACpD,SAAS,EAAE,KAAK;YAChB,aAAa,EAAE,UAAU,EAAE;YAC3B,cAAc,EAAE,KAAK;YACrB,QAAQ,EAAE,YAAY;SACvB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;AACrB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export { GodotMcpException } from "./errors.js";
|
|
2
|
+
export { ExtensionRegistry, type ExtensionContext, type ExtensionDefinition, type ExtensionEvidenceWriter } from "./extensions/extensionRegistry.js";
|
|
3
|
+
export { UNSAFE_CONFIRMATION_PHRASE, approveUnsafeFixtureCopy, consumeUnsafeFixtureActivation, registerUnsafeFixture, stampUnsafeFixtureCopy, type UnsafeActivation, } from "./unsafe/unsafeFixtureAuthority.js";
|
|
4
|
+
export { UnsafeFixtureProcess, type UnsafeFixtureProcessHandle } from "./unsafe/unsafeFixtureProcess.js";
|
|
5
|
+
export { UnsafeFixtureService, type UnsafeFixtureServiceDependencies } from "./unsafe/unsafeFixtureService.js";
|
|
6
|
+
export { EditorMutationService, editorMutationRequestDigest, type EditorMutationBridge, } from "./editor/editorMutationService.js";
|
|
7
|
+
export { MutationLedger, type MutationLedgerCompleteInput, type MutationLedgerKeyInput, type MutationReconciliation, } from "./editor/mutationLedger.js";
|
|
8
|
+
export { ProjectConfigSchema, createProjectConfig, type ProjectConfig, } from "./project/projectConfig.js";
|
|
9
|
+
export { discoverProject, readProjectIdentity, type DiscoveredProject, } from "./project/projectIdentity.js";
|
|
10
|
+
export { resolveProjectPath, type ProjectPathMode } from "./project/pathPolicy.js";
|
|
11
|
+
export { ArtifactStore, scanArtifactDirectory, type ArtifactScanEntry, type ArtifactScanFinding, type ArtifactScanOptions, type ArtifactScanResult, } from "./project/artifactStore.js";
|
|
12
|
+
export { OwnedProjectProcess, projectProcessFingerprint, projectGodotArguments, recoverOwnedProjectProcess, scrubProjectEnvironment, type ProjectProcessInput, } from "./project/projectProcess.js";
|
|
13
|
+
export { ProjectJobService, type ProjectJobProcess, type ProjectJobServiceDependencies, } from "./project/projectJobService.js";
|
|
14
|
+
export { ProjectJobJournal, type ProjectJobJournalSnapshot, } from "./project/projectJobJournal.js";
|
|
15
|
+
export { ProjectMutationJournal, ProjectMutationService, type ProjectMutationBridge, } from "./project/projectMutationService.js";
|
|
16
|
+
export { ProjectService } from "./project/projectService.js";
|
|
17
|
+
export { assertBuildSolutionsPreflight, assertExportPreflight, projectOperationPreflight, } from "./project/projectPreflight.js";
|
|
18
|
+
export { CORE_CAPABILITIES_POLICY, CORE_CAPTURE_POLICY, CORE_DOCTOR_POLICY, CORE_HELP_POLICY, CORE_POLICIES, CORE_QUERY_POLICY, CORE_SESSION_POLICY, EDITOR_POLICIES, EDITOR_POLICY, INPUT_POLICIES, INPUT_POLICY, PROJECT_POLICIES, PROJECT_POLICY, UNSAFE_POLICIES, UNSAFE_POLICY, PHASE_ONE_POLICIES, RUNTIME_CAPTURE_POLICY, RUNTIME_POLICIES, RUNTIME_POLICY, VISUAL_POLICIES, VISUAL_POLICY, expandPermissionTiers, visibleCapabilities, type CommandPolicy, type SessionGrants, } from "./policy/capabilities.js";
|
|
19
|
+
export { authorize } from "./policy/authorize.js";
|
|
20
|
+
export { redactAuditValue } from "./audit/redact.js";
|
|
21
|
+
export { EvidenceStore, type EvidenceReference, type JsonEvidenceReference, type PngBaselineManifest, type PngEvidenceMetadata, type PngObservation, } from "./evidence/evidenceStore.js";
|
|
22
|
+
export { JsonlAuditSink, type AuditInput, type AuditSink, } from "./audit/jsonlAuditSink.js";
|
|
23
|
+
export { ensureRuntimeDirectory, runtimeDirectoryPath } from "./auth/runtimeDirectory.js";
|
|
24
|
+
export { PairingDescriptorSchema, consumePairingDescriptor, createPairingDescriptor, type PairingMaterial, type SessionDescriptor, } from "./auth/pairingDescriptor.js";
|
|
25
|
+
export { EnvelopeVerifier, deriveSessionKey, envelopeSigningText, signEnvelope, verifyEnvelope, type EnvelopeVerificationOptions, type UnsignedBridgeEnvelope, } from "./auth/sessionCrypto.js";
|
|
26
|
+
export { getCoreHelp, type CoreHelp, type CoreHelpTopic, } from "./help/coreHelp.js";
|
|
27
|
+
export { SessionService, type CapabilitySummary, type DoctorCheck, type DoctorResult, type PublicAttachment, type PublicSessionSnapshot, type SessionState, } from "./session/sessionService.js";
|
|
28
|
+
export { RuntimeDescriptorSchema, consumeRuntimeDescriptor, createRuntimeDescriptor, type RuntimeDescriptor, type RuntimeDescriptorInput, type RuntimeDescriptorMaterial, } from "./runtime/runtimeDescriptor.js";
|
|
29
|
+
export { AUTHENTICATED_DEBUGGER_COMMANDS, DebuggerClientError, type DebuggerCommand, type DebuggerStopEvent, } from "./runtime/debuggerClient.js";
|
|
30
|
+
export { DebugTokenStore, DebugTokenStoreError, type DebugTokenIdentity, } from "./runtime/debugTokenStore.js";
|
|
31
|
+
export { assertLoopbackListenerOwnedByProcess, assertLoopbackListenersOwnedByProcess, listenerPortsAreDistinct, OwnedGodotProcess, godotRuntimeArguments, scrubRuntimeEnvironment, type OwnedRuntimeProcess, type RuntimeArgumentsInput, } from "./runtime/runtimeProcess.js";
|
|
32
|
+
export { RuntimeService, type RuntimeDebuggerClient, type RuntimeServiceDependencies, type RuntimeSnapshot, type RuntimeState, } from "./runtime/runtimeService.js";
|
|
33
|
+
export { inputTraceEvents, summarizeInputForAudit, traceSha256, type InputAuditSummary, } from "./runtime/inputReceipt.js";
|
|
34
|
+
export { comparePng, type ComparePngInput, type ComparePngOutput } from "./visual/pngComparison.js";
|
|
35
|
+
export { ScenarioService, type ScenarioFrame, type ScenarioRuntime, type ScenarioServiceDependencies, } from "./visual/scenarioService.js";
|
|
36
|
+
export { VisualService, type VisualExecutionResult, type VisualScenarioController, type VisualServiceDependencies, } from "./visual/visualService.js";
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|