executeTool previously cast fullToolInfo.val.tool_type (typed string | null | undefined from the Thermos RetrieveToolResponse) straight to ExecutableType at two sites and fed it into getAuthBuilder. For a non-null but unrecognised tool_type, getAuthBuilder does BUILDER_REGISTRY[type] which is undefined, then new BuilderClass() throws "BuilderClass is not a constructor" (an unhandled 500-style crash).
This PR adds an exported toExecutableType(raw: string | null | undefined): ExecutableType | undefined guard in apps/apollo/src/lib/tool_execution/execute_tool.ts that returns the value only when it is a real ExecutableType enum member, else undefined. In executeTool:
null/undefined tool_type still defaults to ExecutableType.Tool (backward compatibility, unchanged behaviour).Err(new HTTPErrors.BadRequest(...)) (a clean 400) instead of crashing.The validated value is computed once as resolvedToolType and reused at both former cast sites (the getAuthBuilder call and the Thermos executableType log/exec path), so the two blind casts are removed. Error_400 (which HTTPErrors.BadRequest produces) is already in executeTool's return error union, so no caller/route signature changes are needed.
A unit test file execute_tool.toExecutableType.test.ts covers: every valid ExecutableType value round-trips, and null, undefined, an unknown string, an empty string, and wrong-casing near-misses all return undefined.
node_modules is not installed in this worktree, so local typecheck/tests were not run; relying on CI check-types and run-vitest-tests.toExecutableType and Object.values(ExecutableType) in plain node (all pass; Object.values(ExecutableType) = ["tool","recipe"]).fullToolInfo.val.tool_type is string | null | undefined (Thermos ToolsRetrieveToolResponse.tool_type?: string | null), so the guard's parameter type matches and null paths are preserved.HTTPErrors.BadRequest is createErrorClass(Error_400, ...) and Error_400 is already in executeTool's return union, so the new Err needs no route-union change.getAuthBuilder has a single call site, now fed only the validated resolvedToolType, and no other call site in apollo casts tool_type../execute_tool path used by existing sibling tests (execute_tool.composio_metering.test.ts), so no new import-cycle/import-time failure is introduced; filename matches the *.test.ts vitest glob.🤖 Generated with Claude Code