Remove ProviderProxy and use template method pattern
>>> [!note] Migrated issue
<!-- Drupal.org comment -->
<!-- Migrated from issue #3552919. -->
Reported by: [marcus_johansson](https://www.drupal.org/user/385947)
Related to !997
>>>
<h3 id="summary-problem-motivation">Problem/Motivation</h3>
<p>Currently we have a provider proxy that runs reflection class on the actual interfaces. This was done to be able to add events around the operation type executions and some code around tags (which could be an event listener)</p>
<p>The module was already used quite much by the time the ProviderProxy was implemented, that the only way of doing it without breaking changes was to add a reflection method with magic methods to catch all.</p>
<p>This however has some problems for developers - you can not look if the actual provider implements some interface, since the only interface you see is the provider proxy. Also magic methods that catches all methods, make autocompleting problematic.</p>
<p>So we want to use the template design pattern instead, where every operation type method is wrapped in another method. For instance "doChat" in the provider, but "chat" for third parties calling it. Or "doTextToImage" in the provider, but "textToimage" for the third parties calling it. This would also lead to no breaking changes for third parties.</p>
<p>This can be solved by using a base class for each operation type, so instead of the provider implementing an interface, they just extend a base class that implements the interface. This can in theory be checked by the plugin manager that its followed.</p>
<p>We can set via interface/base class that the following pattern is followed:</p>
<ul>
<li>doChat - should be implemented on provider level</li>
<li>chat - should be in the base class</li>
</ul>
<p>So the providers will always do correct by just follow interfaces.</p>
<p>However we are opening up operation types as a true plugin system now and those will not be possible to force to follow a strict adherence how the main calling method should work. We want a generic way of doing a preRequestEvent dispatch and a postRequestEvent dispatch.</p>
<p>This will not be forceable without doing a overriding call method, like "call("chat", $chatInput)", but that one will be very weakly typed and it will cause a breaking change.</p>
<p>The solution under, is solving everything except this and it might be the best we got, but there will be some research done if it can be solved anyway.</p>
<h3 id="summary-proposed-resolution">Proposed resolution</h3>
<ul>
<li>On the AiProviderClientBase add one generic method to start a prerequestevent and postrequestevent</li>
<li>For each operation type, add a base class that implements the interface.</li>
<li>On the call method that third parties uses (chat, textToAudio etc.) add it to the base class and run the generic method before and after a do{method_name} call. So doChat or doTextToAudio. They should take the same input as the calling call.</li>
<li>On the base calls add an abstract to the do{method_name} that the providers will have to implement.</li>
<li>Add these changes to the OpenAiBaseProviderClientBase</li>
<li>Make the provider proxy an empty shell with a deprecation notice for (2.1.x) and removal for (3.x)?</li>
</ul>
issue