import { createErrorResponse, createStructuredResponse, extractGdError, getErrorMessage, } from './godot-runner.js'; export const MAX_RUNTIME_ERROR_CONTEXT_LINES = 30; /** * Wraps the execute + empty-stdout-check + try/catch around a headless GDScript * operation. Used by the 15 scene/node mutation handlers in tools/scene-tools.ts * and tools/node-tools.ts to eliminate identical error-handling duplication. * * Handlers retain control of: parameter normalization, project/scene validation, * field validation, and constructing the `params` object — those run before the * call. Success-shape construction (the JSON wrapping the GDScript stdout) is * also unchanged: this helper just returns `{ content: [{ type: 'text', text: stdout }] }`, * which is the exact shape every handler produced previously. */ export async function executeSceneOp(runner, operation, params, projectPath, failurePrefix, emptyStdoutSolutions, exceptionSolutions = ['Ensure Godot is installed correctly'], options = {}) { try { const { stdout, stderr } = await runner.executeOperation(operation, params, projectPath); if (!stdout.trim()) { return createErrorResponse(`${failurePrefix}: ${extractGdError(stderr)}`, emptyStdoutSolutions); } if (options.parseStdoutAsJson) { try { const payload = JSON.parse(stdout.trim()); return createStructuredResponse(payload); } catch (parseErr) { return createErrorResponse(`${failurePrefix}: GDScript returned invalid JSON (${getErrorMessage(parseErr)})`, [ 'This indicates a bug in godot_operations.gd — the operation should emit a JSON payload matching its outputSchema', 'Check get_debug_output for the raw stdout and stderr', ]); } } return { content: [{ type: 'text', text: stdout }] }; } catch (error) { return createErrorResponse(`${failurePrefix}: ${getErrorMessage(error)}`, exceptionSolutions); } } /** * Parse a JSON frame returned by the McpBridge. On failure, returns a * structured error response so handlers can short-circuit with one branch. * `context` should describe which bridge command produced the frame. */ export function parseBridgeJson(responseStr, context) { try { return { ok: true, data: JSON.parse(responseStr) }; } catch (error) { return { ok: false, response: createErrorResponse(`Invalid response from bridge (${context}): ${getErrorMessage(error)}`, [ 'The bridge returned non-JSON data — check Godot stderr via get_debug_output', 'Restart the project with stop_project followed by run_project', ]), }; } } /** * Attach captured runtime errors as a `warnings` array on a tool response * payload. No-op when there are no runtime errors. Truncates to * `MAX_RUNTIME_ERROR_CONTEXT_LINES` to keep payloads bounded. */ export function attachRuntimeWarnings(target, runtimeErrors) { if (runtimeErrors.length > 0) { target.warnings = runtimeErrors.slice(0, MAX_RUNTIME_ERROR_CONTEXT_LINES); } } //# sourceMappingURL=handler-helpers.js.map