feat: add plugin tool handler support via metadata lookup
ActionExecutor now checks app.smartAssistant.tools.{name}.handler
metadata for unknown tools before throwing. This allows extensions
to register their own tool handlers without modifying SmartAssistant.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,18 +7,21 @@ use Espo\Core\Exceptions\NotFound;
|
|||||||
use Espo\Core\InjectableFactory;
|
use Espo\Core\InjectableFactory;
|
||||||
use Espo\ORM\EntityManager;
|
use Espo\ORM\EntityManager;
|
||||||
use Espo\Core\Utils\Log;
|
use Espo\Core\Utils\Log;
|
||||||
|
use Espo\Core\Utils\Metadata;
|
||||||
|
|
||||||
class ActionExecutor
|
class ActionExecutor
|
||||||
{
|
{
|
||||||
private EntityManager $entityManager;
|
private EntityManager $entityManager;
|
||||||
private InjectableFactory $injectableFactory;
|
private InjectableFactory $injectableFactory;
|
||||||
private Log $log;
|
private Log $log;
|
||||||
|
private Metadata $metadata;
|
||||||
|
|
||||||
public function __construct(EntityManager $entityManager, InjectableFactory $injectableFactory, Log $log)
|
public function __construct(EntityManager $entityManager, InjectableFactory $injectableFactory, Log $log, Metadata $metadata)
|
||||||
{
|
{
|
||||||
$this->entityManager = $entityManager;
|
$this->entityManager = $entityManager;
|
||||||
$this->injectableFactory = $injectableFactory;
|
$this->injectableFactory = $injectableFactory;
|
||||||
$this->log = $log;
|
$this->log = $log;
|
||||||
|
$this->metadata = $metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
public const VALID_STATUSES = [
|
public const VALID_STATUSES = [
|
||||||
@@ -46,7 +49,7 @@ class ActionExecutor
|
|||||||
'generate_document' => $this->generateDocument($params, $caseId),
|
'generate_document' => $this->generateDocument($params, $caseId),
|
||||||
'merge_documents' => $this->mergeDocuments($params, $caseId),
|
'merge_documents' => $this->mergeDocuments($params, $caseId),
|
||||||
'save_memory' => $this->saveMemory($params, $caseId, $userId),
|
'save_memory' => $this->saveMemory($params, $caseId, $userId),
|
||||||
default => throw new Error("Unknown tool: {$tool}"),
|
default => $this->executePluginTool($tool, $params, $caseId, $userId),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,4 +356,23 @@ class ActionExecutor
|
|||||||
if ($bytes >= 1024) return round($bytes / 1024, 1) . ' KB';
|
if ($bytes >= 1024) return round($bytes / 1024, 1) . ' KB';
|
||||||
return $bytes . ' B';
|
return $bytes . ' B';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function executePluginTool(string $tool, array $params, ?string $caseId, string $userId): array
|
||||||
|
{
|
||||||
|
$handlerClass = $this->metadata->get(['app', 'smartAssistant', 'tools', $tool, 'handler']);
|
||||||
|
|
||||||
|
if (!$handlerClass) {
|
||||||
|
throw new Error("Unknown tool: {$tool}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->log->debug("SmartAssistant: Executing plugin tool={$tool} handler={$handlerClass}");
|
||||||
|
|
||||||
|
$handler = $this->injectableFactory->create($handlerClass);
|
||||||
|
|
||||||
|
if (!method_exists($handler, 'execute')) {
|
||||||
|
throw new Error("Plugin tool handler {$handlerClass} must have an execute() method.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $handler->execute($params, $caseId, $userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user