Skip to content

Commit d1f308a

Browse files
committed
refactor(Tool): streamline handler resolution in Tool class
- Introduced a new method `resolveHandler()` to encapsulate the logic for determining the callable handler for the tool. - Simplified the `handle()` method by delegating handler resolution to `resolveHandler()`, improving readability and maintainability. - Enhanced error handling for cases where no valid handler is defined, ensuring consistent behavior across invokable subclasses.
1 parent a8d0798 commit d1f308a

1 file changed

Lines changed: 30 additions & 13 deletions

File tree

src/Tool.php

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -266,19 +266,7 @@ public function failedHandler(): null|false|Closure
266266
public function handle(...$args): string|ToolOutput|ToolError
267267
{
268268
try {
269-
$fn = $this->fn ?? (method_exists($this, '__invoke') ? $this : null);
270-
271-
if ($fn === null) {
272-
throw new PrismException("Tool handler not defined for tool: {$this->name}");
273-
}
274-
275-
// After ProcessDriver deserialization, $fn may become a
276-
// SerializableClosure\Serializers\Native whose __invoke doesn't
277-
// forward PHP 8 named arguments. Unwrap via getClosure() to
278-
// recover the real Closure so named-arg spreading works.
279-
$callable = is_object($fn) && method_exists($fn, 'getClosure')
280-
? $fn->getClosure()
281-
: $fn;
269+
$callable = $this->resolveHandler();
282270

283271
$value = call_user_func($callable, ...$args);
284272

@@ -299,6 +287,35 @@ public function handle(...$args): string|ToolOutput|ToolError
299287
}
300288
}
301289

290+
/**
291+
* Resolve the callable handler for this tool.
292+
*
293+
* Priority: explicit $fn > invokable subclass (__invoke) > error.
294+
* Also unwraps SerializableClosure wrappers that break named arguments.
295+
*/
296+
protected function resolveHandler(): callable
297+
{
298+
$fn = $this->fn;
299+
300+
if ($fn === null && method_exists($this, '__invoke')) {
301+
$fn = $this;
302+
}
303+
304+
if ($fn === null) {
305+
throw new PrismException("Tool handler not defined for tool: {$this->name}");
306+
}
307+
308+
// After ProcessDriver deserialization, $fn may become a
309+
// SerializableClosure\Serializers\Native whose __invoke doesn't
310+
// forward PHP 8 named arguments. Unwrap via getClosure() to
311+
// recover the real Closure so named-arg spreading works.
312+
if (is_object($fn) && method_exists($fn, 'getClosure')) {
313+
return $fn->getClosure();
314+
}
315+
316+
return $fn;
317+
}
318+
302319
protected function shouldHandleErrors(): bool
303320
{
304321
return $this->failedHandler !== false;

0 commit comments

Comments
 (0)